Leetcode-476. Number Complement C++解

我的解法:

1.题意要素:

(1)正整数

(2)前驱的0不计入置反的操作,比如5的二进制值位00000101,那么其会被置反的只有‘101’这部分,前面的0都不算。

2.关键技巧:

和‘1’相与结合右移可以达到判断某一位是否为0的目的,能够知道哪个位是哪个值就能累加到最终结果。

3.具体解法:

声明一个变量n记录当前操作的位,作为累加的幂。将其逐位右移直到变为0,右移时还要n+1记录当前操作的位数。每次右移前与1相与,如果结果是0,则代表该位源值为0,最终结果就需要累加2^n。

#include <iostream>
#include <cmath>
using namespace std;
int findComplement(int num);


int main(){
	int num;
	cin >> num;
	cout << findComplement(num) << endl;
	return 0;
}


int findComplement(int num) {
	int cp = 0;
	int power = 0;
	if(!num){
		return 1;
	}
	while(num != 0){
		if((num & 1) == 0){
			cp += pow(2, power);
		}
		power++;
		num = num >> 1;
	}
    return cp;
}


网上的另一种解法,觉得挺巧妙的,然而并没有变快,也是3ms,出处:https://discuss.leetcode.com/topic/74897/maybe-fewest-operations/2

int findComplement(int num) {
    int mask = num;
    mask |= mask >> 1;
    mask |= mask >> 2;
    mask |= mask >> 4;
    mask |= mask >> 8;
    mask |= mask >> 16;
    return num ^ mask;
}
大致思路就是:

        首先分析题意。可将题意总结为将给定数字和一个特定的掩码进行XOR操作(异或操作)。这个掩码和给定数有同样的位数,且在其最高位右边全部都是1。以5为例,其二进制表示为101,那5就有3位,那么5(101)对应的掩码为111,5和掩码111异或操作后就可以得到101,也就是题意要求的结果。另一个掩码的例子是38(100110)的掩码是111111。

     这样一来,问题就浓缩成了“如何获取这个掩码”。我们知道,不管是啥正整数,其最高位必定是1,我们可以将其最高位不断右移,来填满余下的低位,得到一个从最高位开始向右都为1的掩码。先看下一个8位的数字,后面可以延伸到32位。以64(01000000)为例,我们的目的是将第6-1位置为1。一开始第7位是1,mask |= mask>>1 将第6位也置为1,这样就得到了01100000。接下来是mask |= mask>>2 ,将5和4位置为1,得到011110000。这里移动2位,因为经过第一步我们已经将mask的高两位置为1了,所以可以移动两位来节省操作,当然你也可以逐位移动。 接下来以为高4位被置为1了,可以移动4位,得到01111111这样就全部置为1了,当然你也可以移动1,2,4位,随你喜欢。

      32位如何移,可以看源码自行理解。


原文如下:

@NoAnyLove To understand the solution, we need to go backwards. The aim is to xor the given number with a mask. The mask should contain all 1s in its rightmost bits. 
However, the number of rightmost bits is important. In the case of 5(101), for example, the number of rightmost bits must be 3, since 5 uses 3 rightmost bits. 
The mask must be 111 for 5(101). When we xor 111 with 101, we will get 010. As another example, the mask will be 111111 for 38(100110)


So the problem boils down to generating the mask. Let's think about 8-bit numbers. We can later extend the same logic to 32-bit integers. 
I will count the bits from right to left, starting with 1.


The largest positive numbers represented by 8 bits will set 7th bit. 64(01000000) is the largest positive number represented by 8 bits,
 which has the most number of 0s. It is important for our explanation since we must turn all those 0s into 1s.


The first operation, mask |= mask>>1; will set the 6th bit. So, mask will become (01100000). Now, we know that the 7th and 6th bits are set, 
we can safely shift the mask to right by not 1 but 2 bits. mask |= mask>>2; will now set the 5th and 4th bits. By the same reason, 
we can now shift the mask to right by not 1, 2 or 3 but 4 bits. That is the threshold for 8-bit numbers. We do not need to shift more.


For 32-bit integers, the shift operations should continue until reaching to 16. For 64-bit longs, that will be 32.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值