Leetcode问题1009 十进制整数的补数

huangapple go评论67阅读模式
英文:

Leetcode Problem 1009 Complement of base 10 integer

问题

Your mistake appears to be in the logic of your code. When you flip the bits of a binary number to find its complement, you should not convert it to a decimal number using base 10. Instead, you should continue working with binary representation until the end.

Here's a corrected version of your code:

class Solution {
public:
    int bitwiseComplement(int n) {
        if (n == 0) {
            return 1; // Special case when n is 0
        }

        long int binary = 0;
        long int i = 0;

        // Calculate the binary complement
        while (n) {
            long int bit = n & 1;
            if (bit == 0) {
                bit = 1;
            } else {
                bit = 0;
            }
            binary = (bit << i) | binary; // Use binary operations instead of pow and base 10

            n >>= 1;
            i++;
        }

        return static_cast<int>(binary); // Convert back to int
    }
};

This code should give you the correct complement in binary representation, and you don't need to convert to base 10 in between.

英文:

The complement of an integer is the integer you get when you flip all the 0's to 1's and all the 1's to 0's in its binary representation.
For example, The integer 5 is "101" in binary and its complement is "010" which is the integer 2.
Given an integer n, return its complement.

My solution -

class Solution {
public:
    int bitwiseComplement(int n) {
        int k=1;
        if(n==0){
            return k;
        }
        long int binary=0,i=0;
        while(n){
            long int bit=n&amp;1;
            if(bit==0){
                bit=1;
            }
            else{
                bit=0;
            }
            binary=(bit*pow(10,i))+binary;
            n=n&gt;&gt;1;
            i++;
        }
        long int ans=0,j=0;
        while(binary!=0){
            long int digit=binary%10;
            ans=digit*pow(2,j)+ans;
            j++;
            binary=binary/10;
        }
        
        
        return ans;
        
    }
};

What is my mistake here?
All my testcases ran successfully but When input is 299475, Output is 224816, Expected output is 224812.
Please help me.

答案1

得分: 3

以下是您要翻译的部分:

"其他评论中已经建议,有位翻转运算符 ~ ,它会反转整数中的所有位。

像 "5" 这样的数字在二进制中表示如下,假设是一个 32 位整数:

0000000 0000000 0000000 0000101

因此,应用这个操作:

int n = 5;
n = ~5;

会得到 n 的如下表示:

11111111 11111111 11111111 11111010

哎呀,这就像是 -6,而不是问题所需的 2。您需要重新处理那些前导的 1 位,直到遇到第一个 0(从左到右)。

将所有内容放在一起。

int bitwiseComplement(int n) {

    if (n == 0)
    {
        return 1; // 特殊情况
    }

    int i = ~n;
    size_t bits = sizeof(n) * 8;

    // 做位操作练习总是一个好主意
    // 在无符号空间中进行 - 尤其是右移操作
    unsigned int mask = 1 << (bits-1);  // 这应该是 0x80000000
    while (mask & i)                    // 当 u 中与 mask 中的位都设置时
    {
        i = mask ^ i;                   // 切换 u 中的位为零
        mask = mask >> 1;               // mask 右移(例如从 0x80000000 到 0x40000000)
    }
    return i;
}"
英文:

As others in the comments have suggested, there's the bit-flip operator ~ that inverses all the bits in an integer

A number like "5" is this in binary. Assuming a 32-bit integer.

0000000 0000000 0000000 0000101

And so applying this:

int n = 5;
n = ~5;

Produces this for n:

11111111 11111111 11111111 11111010

oops, that's like -6, not 2 like the problem wanted. You need to re-twiddle those leading 1 bits and stop when you encounter the first 0 (from left to right).

Putting it altogether.

int bitwiseComplement(int n) {

    if (n == 0)
    {
        return 1; // special case
    }

    int i = ~n;
    size_t bits = sizeof(n) * 8;

    // it&#39;s always a good idea to do bit-twiddling exercises
    // in the unsigned space - especially for the right shift
    unsigned int mask = 1 &lt;&lt; (bits-1);  // this should be 0x80000000
    while (mask &amp; i)                    // while the bit in u matching the bit in mask are both set
    {
        i = mask ^ i;                   // toggle the bit in u to zero
        mask = mask &gt;&gt; 1;               // mask gets shifted (e.g. 0x80000000 to 0x40000000)
    }
    return i;
}

答案2

得分: 2

c++20新增了许多有用的位操作函数。如果你能找到一个生成方便的基数 111...111(具有适当数量的1)的函数,那么你可以对原始数字进行异或 (^=) 操作。这样的数字可以通过从 std::bit_ceil 的结果中减去 1 来轻松生成。

更可靠的做法是将其转换为无符号类型。你还需要一个最新的编译器。

遗憾的是,n=0 是一个特殊情况。

#include <iostream>
#include <bit>

int bitwiseComplement(int n)
{
   return n ? n ^= std::bit_ceil(n + 1u) - 1 : 1;
}

int main()
{
   std::cout << bitwiseComplement(299475);
}

输出:

224812
英文:

c++20 added many useful bit-related functions. If you can find one that produces the convenient base 111...111 (with appropriate number of ones) then you can xor (^=) your original number. Such a number is easily produced by subtracting 1 from the result of std::bit_ceil.

It's more reliable to cast to unsigned. You'll also need an up-to-date compiler.

Sadly, n=0 is a special case.

#include &lt;iostream&gt;
#include &lt;bit&gt;
 
int bitwiseComplement( int n )
{ 
   return n ? n ^= std::bit_ceil( n + 1u ) - 1 : 1;
}

int main()
{
   std::cout &lt;&lt; bitwiseComplement( 299475 );
}

Output:

224812

答案3

得分: 0

selbie的答案非常好。此外,该答案表明使用~运算符需要进一步的工作。这里有另一个有效的解决方案,更简单,二进制操作次数更少。

class Solution {
public:
    int bitwiseComplement(int n) {
        
        if(n==0){
            return 1;
        }
        int comp_op=0;
        int i=0;
        while(n){
            int bit=n&1;
            int add_val = 0;
            if (bit == 0)
                add_val = 1<<i;
            comp_op += add_val;
            n >>= 1;
            i++;
        }
        return comp_op;
    }
};

selbie关于使用无符号整数进行位操作的观点非常正确。在这种情况下,LeetCode问题允许我们假设该数字是非负的(0 <= n < 10^9)。此外,问题陈述不清楚当n = 0时应该做什么。上面的代码被LeetCode接受,我们可以假设当n = 0时,1是预期的输出。此外,他们提到问题1009与另一个问题相同(leetcode.com/problems/number-complement),其中n的范围为1 <= n < 2^31,这是明确的。

如果在位操作问题中,n可以为负数,那么根据n>>1来进展和退出的while循环不是一个好主意。我们应该根据数字的表示中的位数来进展while循环,就像selbie的答案中所做的那样。然而,如果这个LeetCode问题必须重新定义以允许负数输入,那么问题陈述必须经过仔细和明确的修改,以便了解预期的输出。

根据Aconcagua的下面的评论,

int bit=n&1;
int add_val = 0;
if (bit == 0)
    add_val = 1<<i;
comp_op += add_val;

可以简洁地实现为:

comp_op |= (!(n&1)) << i;
英文:

selbie's answer is very good. Also, that answer shows that using the ~ operator requires further work to be done. Here is another solution that works. It is somewhat simpler with less number of binary operations.

class Solution {
public:
    int bitwiseComplement(int n) {
        
        if(n==0){
            return 1;
        }
        int comp_op=0;
        int i=0;
        while(n){
            int bit=n&amp;1;
            int add_val = 0;
            if (bit == 0)
                add_val = 1&lt;&lt;i;
            comp_op += add_val;
            n &gt;&gt;= 1;
            i++;
        }
        return comp_op;
    }
};

selbie's point about doing bit twiddling operations with unsigned integers is very true. In this case, the Leet Code problem let's us assume that the number is non-negative (0 <= n < 10^9). Also, the problem statement is not clear what to do when n = 0. The above code is accepted by Leet Code and we could assume that 1 is the expected output when n = 0. Also, they mention that problem 1009 is the same as another one (leetcode.com/problems/number-complement), where the range of n is 1 <= n < 2^31, which is unambiguous.

If in a bit-twiddling problem, n can be negative, a while loop progressing and exiting based on n&gt;&gt;1 is not a good idea. We should progress the while loop based on number of bits in the representation of the number as it is done in selbie's answer. However, if this Leet Code problem has to be re-framed to allow negative input numbers, the statement of the problem has to be refined carefully and clearly, as to what to expect as output.

As per Aconcagua's comments below,

int bit=n&amp;1;
int add_val = 0;
if (bit == 0)
    add_val = 1&lt;&lt;i;
comp_op += add_val;

can be compactly implemented as,

comp_op |= (!(n&amp;1)) &lt;&lt; i;

huangapple
  • 本文由 发表于 2023年5月15日 15:21:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76251724.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定