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

力扣题目分享:只出现1次的数字I II III(位运算版)

只出现一次的数字 

 这道题目是要找出只出现一次的数字,其他数字都会出现两次

C语言可以直接用的位运算有按位与(&),按位或(|),按位异或(^)

这道题用到的是按位异或

先讲一下按位异或:

 对于两个二进制数,相同为0,不同为1,上图中前两位是不同的,所以只有前两位为1,后三位都为1,所以这两个数按位异或的结果就是00011,即3

 那两个相同的数按位异或的结果就是0

而0和任何数异或都会是另一个数

我们可以利用这个特性,来把所有的数都异或一遍,最后的结果就是单独的那个数了(相同的都变成0了,0和任何数异或都会是另一个数)

本题代码:

class Solution {
public:
    int singleNumber(vector<int>& nums) 
    {
        int num = 0;
        for(auto e : nums)
        {
            num^=e;
        }
        return num;
    }
};

只出现一次的数字II

本题和上题的唯一区别就是从出现两次变成了三次,那肯定不能再用按位异或了,这样异或出来的结果完全没有任何意义

但这一题还是考的位运算操作

先来讲讲按位与和按位或

按位与是双方位都为1才是1,按位或只需要双方有1个为1就是1

思路:

 因为除了那一个数,其他数都出现三次,可以先用按位与来遍历每一个数,用一个[32]的数组把每一个位中的1都统计起来,只要有一位的1的个数不是3的倍数,那多出来的1就是多余的那个数的

具体实现: 

class Solution {
public:
    int singleNumber(vector<int>& nums) 
    {
        int er[32]={0};
        for(auto e : nums)
        {
            for(int i=0;i<32;i++)
            {
                if(e&(1<<i))//如果第i位是1
                {
                    er[i]++;//那么第i位++
                }
            }
        }
        int p=0;
        for(int i = 0;i<32;i++)
        {
            if(er[i]%3 != 0)//如果这一位1的个数不是3的倍数,那多出来的那个1就是属于只出现一次的数的
            {
                p |= (1<<i);//将p的第i位置成1
            }
        }
        return p;
    }
};

只出现一次的数字III

 该题和第一题的区别是只出现一次的数字从1个变成了2个,那有没有什么办法可以将它转换成2个第一题呢?

可以确定的是,这两个只出现一次的数不是一样的,如果将这全部的数都异或,最后是两个只出现一次的数异或的结果,我们就可以通过这个结果来给它分组

具体实现: 

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) 
    {
        int num=0;
        for(auto e : nums)//将所有数都异或一遍,得到的结果就是只出现一次的那两个数异或的结果
        {
            num^=e;
        }
        int i;
        for(i=0;i<32;i++)//判断这个结果的哪一位是1,只要是1就代表这两个数的这一位不同
        {
            if(num & (1 << i))//不同就跳出
                break;
        }
        int num1=0,num2=0;
        for(auto e : nums)//然后根据这个不同的位来对这些数据分组,这样这两个只出现一次的数就被分到两组了
        {
            if(e & (1 << i))
                num1 ^= e;//就化解成了问题1了
            else
                num2 ^= e;
        }
        vector<int> v;
        v.push_back(num1);
        v.push_back(num2);
        return v;
    }
};

相关文章:

  • 宝塔docker flarum默认登录账号密码,crazymax/flarum镜像默认登录账号密码
  • 蓝桥杯算法题分享(二)
  • 从 Copilot 到垂直工具:AI 编程的 “专精特新“ 进化论
  • 用python写网络爬虫
  • 如何用Spring AI构建MCP Client-Server架构
  • 动手实践:单机安装高性能列式存储数据库ClickHouse
  • 根据模板将 Excel 明细数据生成 PDF 文档 | PDF实现邮件合并功能
  • 大数据学习(85)-Flume详解
  • mysql学习-索引规则
  • 蓝桥杯 回文字符串
  • 09_JavaScript数据操作方法_数组2
  • 基于Zookeeper的微服务配置管理与灰度发布实战指南
  • WEB API 设计规范
  • Leetcode——1047. 删除字符串中的所有相邻重复项
  • 阶跃星辰开源300亿参数视频模型Step-Video-TI2V:运动可控+102帧长视频生成
  • Hyperlane 似乎是一个轻量级、高性能的 Rust HTTP 服务器库
  • Redis原理:Monitor 实现
  • 雕马快租:直播设备租赁新趋势,低成本重构传统营销模式的破局之道
  • 缓存相关问题
  • 单例模式在Python中的实现和应用
  • 吴玉凤获任杭州市政协副秘书长,此前担任富阳区委书记
  • 美“金穹”反导系统增加外空作战手段,外交部:中方严重关切
  • 深一度|有望冲击首轮秀?杨瀚森走出舒适圈站上大舞台
  • 财政部:鼓励政策性银行对符合条件的城市更新项目提供支持
  • “敌人已经够多了”,菲总统马科斯:愿与杜特尔特家族和解
  • 人民日报任平:从“地瓜经济”理论到民营经济促进法,读懂中国经济的成长壮大之道