LeetCode1017题:负二进制转换(原创)

【题目描述】

        给你一个整数 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

【题目链接】. - 力扣(LeetCode)

【解题代码】

package number;

public class BaseNeg2 {

    public static void main(String[] args) {
        System.out.println("计算结果:" + new BaseNeg2().baseNeg2(4));
    }

    public String baseNeg2(int n) {
        // 定义一个字符串生成器
        StringBuilder sb = new StringBuilder();
        // 当前数据总和
        int sum = 0;
        // 当前位数值
        int curDigitVal = 1;
        // 当前最高值
        int top = 2;
        while (true) {
            // 如果计入当前位数值,计算当前剩余数值
            int remaining = n - sum - curDigitVal;
            // 计算当前剩余数值是否合法:即目前后面位数不得为1
            if ((remaining & (top - 1)) == 0) {
                // 如果合法,计入当前位数值,字符串生成器加“1”
                sum += curDigitVal;
                sb.append(1);
            } else {
                // 如果不合法,计入当前位数值,字符串生成器加“0”
                sb.append(0);
            }
            // 如果当前数据总和等于目标值,跳出循环
            if (sum == n) {
                break;
            }
            // 当前负二进制位数左移1位
            curDigitVal *= -2;
            // 当前最高位左移1位
            top <<= 1;
        }

        return sb.reverse().toString();
    }
    
    // 第一次的老代码
    public String baseNeg21(int n) {
        StringBuilder sb = new StringBuilder();
        int sum = 0;
        int i = 0;
        while (true) {
            int curDigitVal = (int) Math.pow(-2, i++);
            int mask = (1 << i) - 1;
            int tmp = n - sum - curDigitVal;
            if (tmp % 2 == 0 && (tmp & mask) == 0) {
                sum += curDigitVal;
                sb.append(1);
            } else {
                sb.append(0);
            }
            if (sum == n) {
                break;
            }
        }

        return sb.reverse().toString();
    }
}

【解题思路】

        拿到题目第一眼感觉没有什么思路,于是看了下提示:

意思是根据提示可得知此题的关键点就在于检查当前负二进制位是否计入数值,然后再逐个左移检查,根据示例可以猜想出当前二进制位是否合理点:

  1. 目标值减去当前所有计入数值负二进制位之和的余数,能被2整除;
  2. 目标值减去当前所有计入数值负二进制位之和的余数,不可以包含低位2进制。因为往后添加的都是高位二进制;

按照这个思路很快写出代码,并提交成功

但运行结果执行用时分布是1MS,不是理想的0MS,应该哪里可以优化一下, 仔细检查了下代码,看到m,k等数值存在重复计算,于是又优化了一下。最终达到预计的0毫秒

【解题步骤】

  1. 定义字符串生成器,当前数据总和,当前位数值,当前最高值等变量;
    StringBuilder sb = new StringBuilder();
    int sum = 0;
    int curDigitVal = 1;
    int top = 2;
  2. 开启一个循环逐个检查当前负二进制位,计算出如果计入当前负二进制位数值,前剩余数值;
    while (true) {
        int remaining = n - sum - curDigitVal;
  3.  如果剩余数值合法,计入当前位数值,字符串生成器加“1”,否则字符串生成器加“0”
    if ((remaining & (top - 1)) == 0) {
        sum += curDigitVal;
        sb.append(1);
    } else {
        sb.append(0);
    }}
          
  4. 如果当前数据总和等于目标值,跳出循环
    if (sum == n) {
        break;
    }
  5. 当前负二进制位数左移1位,当前最高位左移1位
    curDigitVal *= -2;
    top <<= 1;
  6. 字符串生成器中逆序返回结果字符串 
     return sb.reverse().toString();

【思考总结】

  1. 此题解法的关键点就在于“目标值减去当前所有计入数值负二进制位之和的余数,不可以包含低位2进制”
  2. 程序员对于与、或、非、移位等这些位操作基本功一定要十分精通,了然于胸;
  3. 算法优化要精益求精:关键点要斤斤计较,拒绝重复计算;
  4. LeetCode解题之前,一定不要看题解,看了就“破功”了!
  • 24
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值