首页 > 代码库 > LeetCode解题思路:476. Number Complement

LeetCode解题思路:476. Number Complement

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.

题意:给定一个整数,输出另一个整数。对这个数的要求是原数转换成二进制后,从高向低第一个1开始按位取反所得到的数。

基本思路:

1.最常规想法:定义1个长度为32的int(bool/char/type) 数组,把原数二进制展开,然后数0,并在数组中相应的位置上写1,到最后一个1为止。然后再把数组变成一个二进制数,然后就能得到想要的数。代码如下(找最后一个1的方式有点蠢,不仅适合正数也适合负数):

 1 int findComplement(int num) {
 2     int a[32] = {0};//定义数组
 3     int cnt = 0;
 4     while(num)
 5     {
 6         a[cnt++] = (num%2)^1;//保存元素
 7         num/=2;
 8     }
 9     while(a[cnt] == 0 && cnt > 0)//找数组最后的位置
10         cnt--;
11     cnt ++;
12     int i = 0;
13     int ret = 0;
14     while(i<=cnt)
15     {
16         ret += (1<<i)*a[i];//把数组转化成数
17         ++i;
18     }
19     return ret;
20 }

2. 用上面的方法是3ms并不慢。当然并不是没有简单的方法,这题看上去就像按位取反,然而按位取反并不太可行,因为5取反等于-6,仍然要去掉高位的1,才能得到想要的数。最后仍然要去统计高位有多少个1,保存在一个数组或数中再进行操作。

3. 不过保存在1个数中,从占用的空间上看多少能让我们觉得更加欣慰一点,多少有一点优化好过没有优化,既然都要把这个数转化成二进制,那我们可以顺手构造一个新的数,让他的每一位都为1,并且位数和原来的数相等,然后用这个数和原来的数直接异或并返回。这种查位的方法只适合正数(题中也说的是正数)

1 int findComplement(int num) {
2     int i = 0,ret = 0,tmp = num;
3     while((tmp/=2)!=0)
4        ret += 1<<i++;
5     ret+=1<<i;//因为/=2先进行后判断,所以要后加一次
6     return ret^num;//这里也可以改成ret-num,当然这并不是位操作实现减法的原理
7 }

当然结果仍然是3ms 代码看上去倒是简洁了不少。

更简洁的方法就是思路2,我自己想了半天觉得没有特别简单的方法就没写

以下来自LeetCode lzl124631x137大神,适合正数和负数

1 class Solution {
2 public:
3     int findComplement(int num) {
4         unsigned mask = ~0;//将掩码各位全设1
5         while (num & mask) mask <<= 1;//掩码左移确定num位数
6         return ~mask & ~num;//取反再取与
7     }
8 };

还有一个比较奇特的方法,由于给的是正整数所以这种方法是可行的的,如果包含负数这种将不可行

1 int findComplement(int num) {
2     int mask = num;
3     mask |= mask >> 1;
4     mask |= mask >> 2;
5     mask |= mask >> 4;
6     mask |= mask >> 8;
7     mask |= mask >> 16;
8     return num ^ mask;
9 }

有兴趣的可以去看下他的解释:https://discuss.leetcode.com/topic/74897/maybe-fewest-operations。侵删。

 

LeetCode解题思路:476. Number Complement