问题描述
问题链接:https://leetcode.com/problems/number-complement/#/description
Given a positive integer, output its complement number. The complement strategy is to flip the bits of its binary representation.
Note:
The given integer is guaranteed to fit within the range of a 32-bit signed integer.
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开始取反,取反一位以后就把答案向左移动一位。
第一次的代码是这样:
public class Solution {
public int findComplement(int num) {
/*
思路是这样的,从左向右找第一个不是0的位,没找到之前不做处理,找到之后开始凑答案,
如果是1,就把答案向左移一位,如果是0,就把答案向左移一位,并且跟0xFFFFFFFF与一下。
*/
boolean startFlag = false;
int numCopy = num;
int answer = 0;
for(int i = 0; i < 32; i++){
if((numCopy & 0x80000000) == 0x80000000){
if(startFlag == false){
startFlag = true;
}
if(startFlag == true){
answer = answer << 1;
}
}else{
if(startFlag == true){
answer = answer << 1;
answer = answer & 0xFFFFFFFF;
}
}
numCopy = numCopy << 1;
}
return answer;
}
}
我很困扰为什么没有通过,在心里试了一下,发现问题出在这一句里面answer = answer & 0xFFFFFFFF;
我的本意是要把最后一位变成1,但是显然,这样并不能达到我的目标,于是我修改为answer = answer | 0x1;
这样就正确了。
通过的代码
我的通过代码是这样的:
public class Solution {
public int findComplement(int num) {
/*
思路是这样的,从左向右找第一个不是0的位,没找到之前不做处理,找到之后开始凑答案,
如果是1,就把答案向左移一位,如果是0,就把答案向左移一位,并且跟0x1或一下。
*/
boolean startFlag = false;
int numCopy = num;
int answer = 0;
for(int i = 0; i < 32; i++){
if((numCopy & 0x80000000) == 0x80000000){
if(startFlag == false){
startFlag = true;
}
if(startFlag == true){
answer = answer << 1;
}
}else{
if(startFlag == true){
answer = answer << 1;
answer = answer | 0x1;
}
}
numCopy = numCopy << 1;
}
return answer;
}
}
这段代码只打败了4.29%的Java代码,还是要跟讨论区的大神们多多学习。
讨论区
Java 1 line bit manipulation solution
链接:https://discuss.leetcode.com/topic/74642/java-1-line-bit-manipulation-solution
代码只有一行,我们来理解一下。
public class Solution {
public int findComplement(int num) {
return ~num & ((Integer.highestOneBit(num) << 1) - 1);
}
}
首先看到的就是这一句Integer.highestOneBit(num)
,第一感觉是得到最高位的1的位置,但是感觉又说不通。然后猜测是保留最高位的1后面的位全部为0。(后来查资料发现猜对了~)
那么只留下最高位为1的数后左移一位,然后-1,就会得到一个从原来的数最高位的1开始剩下全都是1的数。比如原来的数是5(101),做完这一步之后就会得到(111)。
接下来看~num
,是按位取反。最高位1前面的肯定都是1了,这一部分跟上面得到的掩码相与,肯定是0,不需要考虑了。剩下的部分取反后与掩码相与正好保留下来。符合题目要求。
Java, very simple code and self-evident, explanation
链接:https://discuss.leetcode.com/topic/75605/java-very-simple-code-and-self-evident-explanation
这个也是极有创意的。
for example:
100110, its complement is 011001, the sum is 111111. So we only need get the min number large or equal to num, then do substraction
public int findComplement(int num)
{
int i = 0;
int j = 0;
while (i < num)
{
i += Math.pow(2, j);
j++;
}
return i - num;
}