从零学算法1017

news/2024/11/19 11:32:15/

1017. 负二进制转换
给你一个整数 n ,以二进制字符串的形式返回该整数的 负二进制(base -2)表示。
注意,除非字符串就是 “0”,否则返回的字符串中不能含有前导零。
示例 1:
输入:n = 2
输出:“110”
解释:(-2)2 + (-2)1 = 2
示例 2:
输入:n = 3
输出:“111”
解释:(-2)2 + (-2)1 + (-2)0 = 3
示例 3:
输入:n = 4
输出:“100”
解释:(-2)2 = 4
提示:
0 <= n <= 109

  • 我的原始人解法:最朴素的思路。
    1. 确定至少需要用几位表示 n ,并且得到这几位能表示的最大值 sum。根据定义会发现,由于 -2 的奇数次只会对最大值产生负影响,所以比如 3 位负二进制数和 4 位负二进制数的最大值其实都为 101(-22 + -20) 和 0101(-22 + -20)。
    2. 用负二进制先表示出来,最大值当然是把会得到负数的每一位取 0,其他位取 1,比如 101,10101。
    3. 我们在最大值的基础上减到等于 n,rest = sum - n 就是我们需要在步骤 2 的基础上减去的数,比如 rest = 7,我们总共需要减少 7。
      1. 先得到小于 7 的最大的 2x,即 4,我们需要先减去 4。(减去一个数就相当于把原本 4 对应的那一位取反即可,比如 101 要减 4 -> 001,101 要减 2 -> 111。)
      2. 减了 4 以后,还剩 3 没减,还是同理,先减 2,最后减 1。
  •   public String baseNeg2(int n) {int i = 0;int sum = 1;while(sum < n){i += 2;sum += Math.pow(2, i);}StringBuilder sb = new StringBuilder();while(i >= 0){if(i-- % 2 == 0)sb.append("1");else sb.append("0");}int rest = sum - n;while(rest > 0){int x = getDigit(rest);char c = sb.charAt(sb.length() - 1 - x);String newC = c == '1'? "0" : "1";sb.replace(sb.length() - 1 - x, sb.length() - x, newC);rest -= Math.pow(2, x);}return sb.toString();}// 得到小于 n 的最大的 2 的 x 次对应的那一位public int getDigit(int n){int sum = 0;int i = 0;while(sum < n){sum += Math.pow(2, i++);}return i - 1;}
    
  • 他人题解:看了很多篇题解,个人认为最本质的还是这个。
  • 首先 10 进制转 k 进制,原理都为不断取余,我们顺着这一点解决。
  • 当 k 为正数时,我们很容易写出模版,不断取余,拼接余数,然后 n 整除 k
  • 	if(n == 0)return "0";int k = 2;StringBuilder sb = new StringBuilder();while(n != 0){int r = n % k;sb.append(r);n = n / k;}return sb.reverse().toString();
    
  • 但是当 k 为负数时,余数可能出现负数,那肯定有问题了,比如将十进制的 19 转为 -9 进制,我们会得到如下
    • 19 ÷ −9 = −2 余 1
    • -2 ÷ −9 = 0 余 -2
  • 这里正确的步骤其实应该确保余数大于等于 0,即:
    • 19 ÷ −9 = −2 余 1
    • -2 ÷ −9 = 1 余 7 (-9 * 1 + 7 = -2 -> 7 = -2 + 9)
    • 1 ÷ -9 = 0 余 1
  • 根据第二步的 7 = -2 + 9 所以为了保证余数大于 0,余数应该为 n % k + abs(k),但这是余数为负数的情况;考虑到余数为正数时这样一加结果都大于 k 了,我们最终还是得对 abs(k) 取余,这样当余数为负数时,n % k + abs(k)abs(k) 取余还是 n % k + abs(k);当余数为正数时 (n % k + abs(k)) % abs(k) 其实就还等于 n % k
  • 同理,整除后的结果也需要处理,即 -2 ÷ −9 = 1 余 7 的 1 是怎么来的,我们换位得到 1 = (-2 - 7) ÷ -9,即 (n - r)/k,由于 r 本来就是 n / k 之后的余数,所以 (n - r) / k 等于 n / k
  •   public String baseNeg2(int n) {if(n == 0)return "0";int k = -2;StringBuilder sb = new StringBuilder();while(n != 0){int r = n % k;r = (r + Math.abs(k)) % Math.abs(k);sb.append(r);n = (n - r) / k;}return sb.reverse().toString();}
    

http://www.ppmy.cn/news/1443699.html

相关文章

Linux中的高级IO函数(二)readv writev sendfile mmap splice tee

Linux提供了很多高级的I/O函数。它们并不像Linux基础I/O函数&#xff08;比如open和read&#xff09;那么常用&#xff08;编写内核模块时一般要实现这些I/O函数&#xff09;&#xff0c;但在特定的条件下却表现出优秀的性能。这些函数大致分为三类&#xff1a; 用于创建文件描…

提高分布式软件开发团队协作效率的策略和工具推荐

策略1:采用敏捷开发方法 步骤: 研究敏捷方法: 研究敏捷开发方法,如Scrum或Kanban,了解其原则和实践。培训团队: 为团队成员提供敏捷方法论和最佳实践的培训。选择工具: 选择适合敏捷开发的工具,如Jira、Trello或Asana。实施敏捷仪式: 定期举行站立会议、迭代评审和迭…

基于springboot实现在线课程管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现在线课程管理系统演示 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了在线课程管理系统的开发全过程。通过分析在线课程管理系统管理的不足&#xff0c;创建了一个计算机管理在线课程管理系…

iOS 模拟请求 (本地数据调试)

简介 在iOS 的日常开发中经常会遇到一下情况&#xff1a;APP代码已编写完成&#xff0c;但后台的接口还无法使用&#xff0c;这时 APP开发就可能陷入停滞。此时iOS 模拟请求就派上用场了&#xff0c;使用模拟请求来调试代码&#xff0c;如果调试都通过了&#xff0c;等后台接口…

IT大陆之:指定用户登入docker

这天&#xff0c;S老交给小k一个特殊的任务&#xff1a;以“nav”这个神秘身份&#xff0c;深入“my_dk”国度&#xff0c;探索其中的奥秘。小k心怀激动与忐忑&#xff0c;站在控制台前&#xff0c;深吸一口气&#xff0c;然后缓缓念出那串充满魔力的咒语&#xff1a;“sudo do…

12.7.1 实验7:实施路由器密码恢复

1、实验目的 通过本实验可以掌握&#xff1b; 路由器密码恢复原理。路由器密码恢复步骤。修改配置寄存器值的方法。 2、实验步骤 路由器密码恢复的过程如下所述。 &#xff08;1&#xff09;路由器冷启动。 1分钟内按【CtrlBreak】键进入ROM监控(ROM Monitor ) rommon模式…

Pixelmator Pro for Mac:简洁而强大的图像编辑软件

Pixelmator Pro for Mac是一款专为Mac用户设计的图像编辑软件&#xff0c;它集简洁的操作界面与强大的功能于一身&#xff0c;为用户提供了卓越的图像编辑体验。 Pixelmator Pro for Mac v3.5.9中文激活版下载 该软件支持多种文件格式&#xff0c;包括常见的JPEG、PNG、TIFF等&…

使用Python,结合Flask框架,创建一个可以处理交易、挖矿新区块、验证区块链有效性,并能在网络节点间同步的区块链网络。(持续更新)

目录 前言 二、代码注释 1.添加新交易到区块链 2.连接新节点 3、替换区块链为最长链 总结 前言 本篇文章将从一个实践者的角度出发&#xff0c;通过构建一个简单的区块链系统&#xff0c;揭开区块链技术的神秘面纱。我们将使用Python语言&#xff0c;结合Flask框架&…