【LeetCode】476. Number Complement

问题描述

问题链接: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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值