LeetCode之Number Complement

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012668018/article/details/60760284

Given a positive integer, output its complement number. The complement strategy is to flip the bits of its binary representation.

Note:

  1. The given integer is guaranteed to fit within the range of a 32-bit signed integer.
  2. You could assume no leading zero bit in the integer’s binary representation.

Example 1:

Input: 5
Output: 2
Explanation: The binary representation of 5 is 101 (no leading zero bits), and its complement is 010. So you need to output 2.

Example 2:

Input: 1
Output: 0
Explanation: The binary representation of 1 is 1 (no leading zero bits), and its complement is 0. So you need to output 0.

题设的要求就是把一个正数的各个二进制位取反,取反的意思就是0变1,1变0,比如101变成010,可以看出,取反之后与原数相加就是111。

所以解题思路也很简单,就是找出这个和,减去原数就行了。问题在于如何找到这个和?因为不同的输入,对应的和的二进制中1的个数是不同的。然而可以确定的是,这个和的二进制位数和原数是一致的。所以只要求得原数的位数,就可以算出这个和。我的思路如下:

public int findComplement(int num) {
        int tmp = num, bits = 0;
        while(tmp > 0) {
            bits++;
            tmp = tmp >> 1;
        }

        int sum = 1 << bits - 1;
            
        return sum - num;
 }


while循环中通过右移运算求出原数的位数;然后通过1左移bits个位,得到对应和加1那个值,所以要减去1才是对应的和,然后返回和减去原数。

这种思路是比较原始和直观的,接着做一点优化:

public int findComplement(int num) {
        int tmp = num, sum = 1;
        while(tmp > 0) {
            sum = sum << 1;
            tmp = tmp >> 1;
        }
            
        return sum - 1 - num;
 }


省去了求bits的过程,直接在while中完成左移。


但是看别人的答案的时候,发现了另一种求和的思路:

public int findComplement(int num) {
        int n = 0;
        while (n < num) {
            n = (n << 1) | 1;
        }
        return n - num;
}


这种思路很棒,我们看n的值的变化,就知道它是如何运作的:0,1,11,111,1111,....

那么循环的终止条件为啥那么怪异呢?

我们看n的变化趋势,就是不停的在末位添加一个1,那么n的位数早晚会和原数相等,而和原数位数相等的所有数中,最大的那个肯定是所有位都是1的,原数肯定小于等于此时的n,即n >= num。所以终止条件设为n < num,也就是当n >= num时,n已经是我们想要的那个数了,n不能再增长了。

这个方法中的while循环真的很经典,有好多指的细细品味的地方,它告诉我们,11111这种二进制串是怎么通过位运算造出来的。

补充:

鉴于和的特殊性,这里求补数也可以用异或运算代替减法:

return n ^ num;


猜你喜欢

转载自blog.csdn.net/u012668018/article/details/60760284