【位运算】B007_LC_将二进制表示减到 1 的步骤数(字符串二级制加法 / BigInteger)

一、题目描述

给你一个以二进制形式表示的数字 s 。请你返回按下述规则将其减少到 1 所需要的步骤数:

  • 如果当前数字为偶数,则将其除以 2 。
  • 如果当前数字为奇数,则将其加上 1 。

题目保证你总是可以按上述规则将测试用例变为 1 。

输入:s = "1101"
输出:6
解释:"1101" 表示十进制数 13 。
Step 1) 13 是奇数,加 1 得到 14 
Step 2) 14 是偶数,除 2 得到 7
Step 3) 7  是奇数,加 1 得到 8
Step 4) 8  是偶数,除 2 得到 4  
Step 5) 4  是偶数,除 2 得到 2 
Step 6) 2  是偶数,除 2 得到 1  

尝试一:库函数 ?

注意:s 的最大长度为 500,计算机中的二进制最多可表示为为 64 位,所以用 Long.parseLong(s, "2") 肯定是不行的。

...

方法二:字符串二进制加法

根据题目规则进行二进制运算:

  • 如果当前字符串为偶数,末尾必定是 0,而偶数需要除以 2,即右移 1 位,把0 移除掉,对数值不影响。
  • 如果当前字符串为奇数,我们需要将二进制串 s 进行二进制加 1 操作。
public int numSteps(String s) {
    StringBuilder sb = new StringBuilder(s);
    int step = 0;
    while (true) {
        if (sb.length() == 1 && sb.charAt(0) == '1')
            break;
        if (sb.charAt(sb.length()-1) == '1') {
            sb = new StringBuilder(addBinary(sb.toString(), "1"));
        } else {
            sb.deleteCharAt(sb.length()-1);
        }
        step++;
    }
    return step;
}
// 字符串二进制加法
public StringBuilder addBinary(String a, String b) {
    char[] s1 = a.toCharArray();
    char[] s2 = b.toCharArray();
    int p1 = s1.length-1, p2 = s2.length-1;
    StringBuilder sb = new StringBuilder();
    int ca = 0;
    while (p1 >=0 || p2 >= 0) {
        int m = p1 >= 0 && s1[p1--] == '1' ? 1 : 0;	//如果sum >= 2(也就是对位都是'1'), 那么ans的相同位置变为'1',否则变为'0'
        int n = p2 >= 0 && s2[p2--] == '1' ? 1 : 0;
        ca += m + n;
        sb.append(ca % 2);
        ca /= 2;	//如果sum两次都加上了1,那么ca/2 == 1可以进位。否则ca == 0
    }
    if (ca > 0) sb.append(ca);
    return sb.reverse();
}

复杂度分析

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( n ) O(n) O(n)

方法三:BigInteger

哈哈,没想到用这个啊…,BigIntegerjava.Math 包中

再次,参数是引用传递,在 add,mod 等操作后,记得对大数赋值。

import java.math.BigInteger;
class Solution {
    public int numSteps(String s) {
        BigInteger num = new BigInteger(s, 2), one = BigInteger.ONE, two = BigInteger.TWO, zero = BigInteger.ZERO;
        int t = 0;
        while (!num.equals(one)) {
            if (num.mod(two).equals(zero)) num = num.divide(two);
            else                           num = num.add(one); 
            t++;
        } 
        return t;
    }
}

复杂度分析

  • 时间复杂度: O ( N ) O(N) O(N)
  • 空间复杂度: O ( 1 ) O(1) O(1)

方法三:bit 和 carry(没想到)

在这里插入图片描述

class Solution {
    public int numSteps(String s) {
        if(s.length() == 0) return 0;
        char[] array = s.toCharArray();
        int step = 0;
        int carry = 0;
        
        for(int i = array.length - 1; i >= 0; i--){
            if(i == 0 && carry == 0) 
            	break;
            if(array[i] - '0' != carry){
                carry = 1;
                step += 1;
            }
            step += 1;
        }
        return step;
    }
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

你可能感兴趣的:(#,字符串,#,【位运算】)