当前位置: 首页 > article >正文

【算法-位运算】求数字的补数

文章目录

  • 1. 题目
  • 2. 思路
  • 3. 代码
  • 4. 小结

1. 题目

476. 数字的补数

对整数的二进制表示取反(0 变 1 ,1 变 0)后,再转换为十进制表示,可以得到这个整数的补数。

  • 例如,整数 5 的二进制表示是 “101” ,取反后得到 “010” ,再转回十进制表示得到补数 2 。

给你一个整数 num ,输出它的补数。

示例 1:

输入: num = 5
输出: 2
解释: 5 的二进制表示为 101(没有前导零位),其补数为 010。所以你需要输出 2 。

示例 2:

输入: num = 1
输出: 0
解释: 1 的二进制表示为 1(没有前导零位),其补数为 0。所以你需要输出 0 。

提示:

  • 1 <= num < 2^31

2. 思路

这道题的逻辑是数字取反,而不是求补码,那么来看下图图解。
在这里插入图片描述
这里的取反是需要找到最高位的 1 然后取反,所以核心逻辑就是如何找到最高位1,如果要找到最高位 1,有两种方法。

第一种方法就是遍历这个 num 的所有位,找到第一个不为空的位,然后直接 break

int index = -1;
for(int i = 31; i >= 0; i--){
    if(((num >> i) & 1) != 0){
        index = i;
        break;
    }
}

找到这个 index 之后,我们就可以继续遍历从 0 到 index,将这部分数据取反即可。

int res = 0;
for(int i = 0; i <= index; i++){
    if(((num >> i) & 1) == 0){
        res |= (1 << i);
    }
}
return res;

上面这种方法需要遍历所有位,那么有没有更方便的方法呢? 还是看下下面图解。
在这里插入图片描述
上面我们以 57 为例子,最终 x = 32,这个 32 就是我们要找的最高位。我们找到这个最高位 32 后,再将 32 - 1,因为最高位取反后肯定为 0,所以换句话说就是要求出剩下的位里面有哪些位是 1,32 - 1 就是将剩下这些位全部变成 1。
在这里插入图片描述
然后将这个数和 ~num 相与,这样求出来结果了。
在这里插入图片描述


3. 代码

首先是第一种方法,第一种方法就比较简单了,直接遍历即可。

public int findComplement(int num) {
    //1.找到最高位的1,然后从小到大逐位取反
    int index = -1;
    for(int i = 31; i >= 0; i--){
        if(((num >> i) & 1) != 0){
            index = i;
            break;
        }
    }
    int res = 0;
    for(int i = 0; i <= index; i++){
        if(((num >> i) & 1) == 0){
            res |= (1 << i);
        }
    }
    return res;
}

第二种方法,从上面的图解中可以看到核心逻辑就是找到最低位的 1,每一次都相减,那么如何找到最低位 1 呢?这就涉及到位运算公式:x & -x 了。
在这里插入图片描述
上面求出了 -num 的值,那么最后再将 num 和 -num 相与,就能求出最低位了。
在这里插入图片描述
好了,上面求出最低位了,最后直接用 -num & (x - 1)直接相与就能求出取反的结果了,下面给出第二种方法的代码:

public int findComplement(int num) {
    int x = 0;
    for(int i = num; i != 0; i -= lowbit(i)){
        x = i;
    }
    //将num的前x-1位取反,因为前面32-x位都是0,所以不用管
    return ~num & (x - 1);
}

//获取当前字符最低位的1
public int lowbit(int x){
    return x & -x;
}

这种方法的计算次数比第一种方法少了几种计算次数,效率更高。


4. 小结

这是灵神题单位运算的一条,这里就记录下思路和所用到的位运算公式:

  • 求最低位 1:x & -x




如有错误,欢迎指出!!!


http://www.kler.cn/a/527793.html

相关文章:

  • 使用 Docker + Nginx + Certbot 实现自动化管理 SSL 证书
  • 最近最少使用算法(LRU最近最少使用)缓存替换算法
  • Transformer+vit原理分析
  • 5.桥模式(Bridge)
  • DeepSeek-R1 模型及GRPO算法学习
  • HTML特殊符号的使用示例
  • 知识库管理在提升客户服务质量中的应用与挑战分析
  • 嵌入式八股文之深入理解 C语言中的指针相关概念
  • 04树 + 堆 + 优先队列 + 图(D1_树(D2_二叉树(BT)(D1_基础学习)))
  • 笔记:电机及控制器的功率测量是怎么进行的?
  • 服务器架构设计大全及其优缺点概述
  • 长尾关键词在SEO提升网站流量中的关键角色与应用技巧分析
  • AVL树介绍
  • Java设计模式:行为型模式→观察者模式
  • LeetCode-180. 连续出现的数字
  • 吉首市城区地图政府附近1公里范围高清矢量pdf\cdr\ai内容测评
  • TCP三次握手和四次挥手面试题
  • WordPress eventon-lite插件存在未授权信息泄露漏洞(CVE-2024-0235)
  • DFS(深度优先搜索)与回溯算法详解
  • LLMs之WebRAG:STORM/Co-STORM的简介、安装和使用方法、案例应用之详细攻略
  • 芯片AI深度实战:给vim装上AI
  • Vue 3 30天精进之旅:Day 10 - Vue Router
  • 计算机毕业设计Python+CNN卷积神经网络考研院校推荐系统 考研分数线预测 考研推荐系统 考研爬虫 考研大数据 Hadoop 大数据毕设 机器学习
  • LeetCode--84. 柱状图中最大的矩形【单调栈】
  • OpenCV:闭运算
  • C++11(中)