LeetCode每日一练(十进制整数的反码)

简介: LeetCode每日一练(十进制整数的反码)

题目如下:

每个非负整数 N 都有其二进制表示。例如, 5 可以被表示为二进制 "101",11 可以用二进制 "1011" 表示,依此类推。注意,除 N = 0 外,任何二进制表示中都不含前导零。二进制的反码表示是将每个 1 改为 0 且每个 0 变为 1。例如,二进制数 "101" 的二进制反码为 "010"。给你一个十进制数 N,请你返回其二进制表示的反码所对应的十进制整数。

在这里插入图片描述

题目要求将一个非负整数二进制的反码表示转为十进制数,比如,5的二进制位101,那么其反码形式为010,以该反码为二进制所对应的十进制整数为2,所以输入整数5,应该得到整数2。

那么首先可以将输入的整数先转为二进制,然后将二进制的反码形式求出来,最后通过该反码转为十进制。

10进制转二进制相信大家都会转,那怎么用代码来实现它呢?可以先来分析一下:
在这里插入图片描述

对于十进制数11,其转为二进制的过程如上图所示,让11除以2,得到商5,余数1,;在让5除以2,得到商2,余数1;最后让2除以2,得到商1,余数0,二进制为1011。
由此得出结论,不断地让输入的数除以2,直至余数为0停止,让最后一次除法的商从下至上拼接所有的余数即可得到二进制,如下所示:
在这里插入图片描述

但在代码的实现过程中,我们只能从上往下除,并不能提前得知后面的商和余数,解决办法也很简单,使用一个StringBuilder,把每次除以2得到的余数放入StringBuilder,除完后将StringBuilder反转,然后将最后一次除法的商插入到StringBuilder的首部即可得到二进制。
在这里插入图片描述

得到二进制后,需要将二进制转为反码形式,只需循环遍历二进制数,当为0时,用1替换;当为1时,用0替换。
在这里插入图片描述

最后以该反码形式表示的二进制再转为10进制,转换也非常简单:0 * 2 ^ 3 + 1 * 2 ^ 2 + 0 * 2 ^ 1 + 0 * 2 ^ 0 = 0 + 4 + 0 + 1 = 5,所以最后的结果为5。

那如何用代码来实现这一过程呢?只需遍历整个二进制数,然后对每一位进行乘法操作,比如0100中的第一位0,它需要乘以2的3次方,而第二位1需要乘以2的2次方,我们可以通过字符串的长度减1再减去当前的位数即可得到幂次。
在这里插入图片描述

最后得出代码如下:

public class Solution {

    public static int bitwiseComplement(int n) {
        // 10进制转为2进制
        StringBuilder sb = new StringBuilder();
        while (n / 2 != 0) {
            int num = n % 2; // 求出余数
            sb.append(num); // 将余数存入StringBuilder
            n = n / 2; // 求出商
        }
        // 反转字符串,并将最后一次除法的商插入到字符串的首部
        String binaryNum = sb.reverse().insert(0, n).toString();
        // 将二进制转为反码形式
        char[] chars = binaryNum.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] == '0') {
                // 如果为0,转为1
                chars[i] = '1';
            } else if (chars[i] == '1') {
                // 如果为1,转为0
                chars[i] = '0';
            }
        }
        // 将反码表示的二进制转回十进制
        int result = 0;
        for (int i = 0; i < chars.length; i++) {
            // 将字符转为数字
            int num = Integer.parseInt(chars[i] + "");
            result += num * Math.pow(2, chars.length - 1 - i);
        }
        return result;
    }
}

提交到LeetCode:
在这里插入图片描述

其实这道题还有一个非常巧妙的解法,我们知道,二进制的反码形式是由原码转换而来的,只需对原码的每一位取反即可,那么它其实可以通过与对应二进制位的全1异或来得到反码,比如:
在这里插入图片描述

11的二进制原码为1011,让其异或相等位数的全1二进制,因为异或的规则为相同为0,不同为1,那么原码中的1因为与之相同就会转为0,而原码中的0因为与之不同就会转为1,所以最终得到0100。

那接下来的问题就转化为了求出位数,因为需要相等位数的全1与其异或,我们可以找找规律,对于整数11,需要四位的全1二进制与其异或,1111表示的十进制为15;对于整数5,需要三位的全1二进制与其异或,111表示的十进制为7,由此得出结论,只需要全1的二进制数大于了输入的整数,那么其位数就一定与之相同。

我们可以从只有1位二进制数1开始计算,当只有1位二进制数1时,对应的十进制为1;
当有2位二进制数11时,对应的十进制为3;
当有3位二进制数111时,对应的十进制为7;
当有4位二进制数1111时,对应的十进制为15;
规律已经非常明显了,它就等于前一个数的2次方加1,即:2n + 1

由此可得代码:

public static void main(String[] args) {
    double num = 1;
    while (num < 11){   // 当num大于11时结束循环
        num = num * 2 + 1; // 在前一个num值的基础上乘以2加1
    }
    System.out.println(num);
}

num = num * 2 + 1;也可以转化为移位操作:num = (num << 1) + 1,向左移一位,表示乘以2的1次方,效果是一样的。

这样就能够得出需要与之异或的值,最后让其直接与输入的整数异或即可:

class Solution {
    public int bitwiseComplement(int N) {
        int num = 1;
        while(num < N){
            num = (num << 1) + 1;
        }
        return num ^ N;
    }
}

提交到LeetCode:
在这里插入图片描述

目录
相关文章
|
2月前
|
存储
LeetCode整数反转
解决LeetCode上的整数反转问题的几种方法,包括错误的方法和优化后的解决方案,以及如何避免反转后的整数超出32位有符号整数范围的问题。
44 1
|
4月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
128 2
|
2月前
【LeetCode】整数翻转
【LeetCode】整数翻转
20 1
|
2月前
|
存储 C++
Leetcode第十二题(整数转罗马数字)
LeetCode第12题“整数转罗马数字”的解题方法,包括罗马数字的基本规则和特殊规则,以及如何使用C++实现整数到罗马数字的转换。
21 0
|
2月前
|
C++
Leetcode第十三题(罗马数字转整数)
这篇文章介绍了LeetCode第13题“罗马数字转整数”的解题方法,通过一个C++的类`Solution`中的`romanToInt`函数来实现,该函数使用哈希表和遍历字符串的方法,根据罗马数字的规则将输入的罗马数字字符串转换为对应的整数值。
57 0
|
2月前
|
算法 C++
Leetcode第八题(字符串转换整数(atoi))
这篇文章介绍了LeetCode上第8题“字符串转换整数(atoi)”的解题思路和C++的实现方法,包括处理前导空格、正负号、连续数字字符以及整数溢出的情况。
22 0
|
4月前
|
算法
LeetCode第12题目整数转罗马数字
该文章介绍了 LeetCode 第 12 题整数转罗马数字的解法,通过使用 TreeMap 按照整数从大到小排序,先使用大的罗马数字表示整数,再用小的,核心是先表示完大的罗马数字,想通此点该题较简单。
LeetCode第12题目整数转罗马数字
|
4月前
|
算法
LeetCode第8题字符串转换整数 (atoi)
该文章介绍了 LeetCode 第 8 题字符串转换整数 (atoi)的解法,需要对字符串进行格式解析与校验,去除前导空格和处理正负号,通过从高位到低位的计算方式将字符串转换为整数,并处理越界情况。同时总结了这几道题都需要对数字的表示有理解。
LeetCode第8题字符串转换整数 (atoi)
|
4月前
|
算法
LeetCode第7题整数反转
该文章介绍了 LeetCode 第 7 题整数反转的解法,通过除 10 取模和乘 10 累加的方式实现整数反转,同时注意边界情况的判断,并总结了通过举例推算发现规律的解题思路。
LeetCode第7题整数反转
|
4月前
|
算法
LeetCode第13题目罗马数字转整数
该文章介绍了 LeetCode 第 13 题罗马数字转整数的解法,通过从大到小解析罗马数字,根据罗马数字的特点,按照从大到小的顺序匹配罗马数字和整数的关系,从而解决该问题,同时强调要注意观察题目考查的知识点特征。