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
- 我的原始人解法:最朴素的思路。
- 确定至少需要用几位表示 n ,并且得到这几位能表示的最大值 sum。根据定义会发现,由于 -2 的奇数次只会对最大值产生负影响,所以比如 3 位负二进制数和 4 位负二进制数的最大值其实都为 101(-22 + -20) 和 0101(-22 + -20)。
- 用负二进制先表示出来,最大值当然是把会得到负数的每一位取 0,其他位取 1,比如 101,10101。
- 我们在最大值的基础上减到等于 n,rest = sum - n 就是我们需要在步骤 2 的基础上减去的数,比如 rest = 7,我们总共需要减少 7。
- 先得到小于 7 的最大的 2x,即 4,我们需要先减去 4。(减去一个数就相当于把原本 4 对应的那一位取反即可,比如 101 要减 4 -> 001,101 要减 2 -> 111。)
- 减了 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();}