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

2 异或位运算大厂必刷题

文章目录

    • 如何不用额外变量交换两个数
    • 一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这种数
    • 怎么把一个int类型的数,提取出最右侧的1来
    • 怎么把一个int类型的数,获取位数为1的数量
    • 一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这两种数
    • 一个数组中有一种数出现K次,其他数都出现了M次

如何不用额外变量交换两个数

int a,b;

a=a^b;
b=a^b;
a=a^b;

注意事项:

  • a和b必须是两块独立的内存.

一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这种数

题解

  • 解法1: 哈希表做词频统计
  • 解法2: 只用一个变量遍历一遍
    • 用eor异或所有人, 把最后结果留在自己身上, 这么干完一遍之后,最后你返回eor的值就是那个出现了奇数次的数.

怎么把一个int类型的数,提取出最右侧的1来

题意:
在这里插入图片描述

题解:

  • a&(~a + 1)
  • 等同于
  • a & (-a)

在这里插入图片描述

怎么把一个int类型的数,获取位数为1的数量

int a;
int nums=0;
while(a)
{
	a=a&(a-1);
	nums++;
}

一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这两种数

题解1:
最常见的解题步骤,面试要求的

void printOddTimesNums(vector<int>& v)
{
    int eor=0;
    for(auto e: v)eor^=e;
    // 假设 a 和 b 是 两种奇数.
    // 从 eor 里随便取一个一位置的数,我们统一取最右侧
    // right = eor & (~eor+1)
    int right = eor & (-eor);
    // 
    // 共有a和b两类的数据 , 将两类数据区分 
    // 我们假设最右侧为1是 属于a类的数据
    // 能够与right按位与不等与0 ,说明属于a类
    int a = 0;
    for(auto e : v)
    {
        if(e & right)
        {
            a^=e;
        }
    }
    int b = eor ^ a;
        cout<< "a="<<a<<endl;
    cout<<"b="<<b<<endl;
    
}

题解2:

void test()
{
    vector<int> v = {1,1,2,2,3,3,3,5,44,55,66,44,55,66,66,66};
    int a =0,b=0;
    int eor =0;
    for(auto e:v)
    {
        eor^=e;
    }
    // eor = a^b
    
    int tmp=eor;
    int i=0;
    int pre=0; // 求出a或者b的数
    while(tmp)
    {
        pre=tmp;
        tmp^=v[i];
        i++;
    }
    cout<< "a="<<pre<<endl;
    cout<<"b="<<(pre^eor)<<endl;
}

一个数组中有一种数出现K次,其他数都出现了M次

题意:一个数组中有一种数出现K次a元素,其他数都出现了M次,M> 1,K<M我到,出现了次的数,要求,额外空复杂度0(1),时间复杂度ON)。

题解:

  • 开一个 32位int的数组 v
  • if v[i] % m == 0 说明 二进制第i位没出现过a元素。
int onlyKTimes(vector<int> &v, int k, int m)
{
    vector<int> t(32, 0);
    // t[0] 0位置的1出现了几个
    // t[i] i位置的1出现了几个
    for (auto num : v)
    {
        for (int i = 0; i <= 31; i++)
        {
            if ((num >> i) & 1 == 1)
            {
                t[i]++;
            }
        }
    }
    int ans = 0;
    for (int i = 0; i <= 31; i++)
    {
        if (t[i] % m != 0)
        {
            ans |= (1 << i);
        }
    }
    return ans;
}

对数器验证算法:

int testonlyKTimes(vector<int> &v, int k, int m)
{
    unordered_map<int, int> map;
    for (auto num : v)
    {
        if (map.find(num) != map.end())
        {
            map[num]++;
        }
        else
        {
            map[num] = 1;
        }
    }
    int ans = 0;
    for (auto num : map)
    {
        if (num.second == k)
        {
            ans = num.first;
            break;
        }
    }
    return ans;
}

vector<int> randomArray(int kinds, int range,int k, int m)
{
    int kNum = rand()% range + 1;
    int times = k; // kNum 出现k次
    int numkinds = rand() % kinds + 1;
    // k*1 + (numkinds - 1) * m;
    vector<int> v(k+ (numkinds-1)*m);
    int index = 0 ;
    for(;index<times;index++)
    {
        v[index] = kNum;
    }
    numkinds--;
    unordered_set<int> set;
    set.insert(kNum);
    while(numkinds!=0)
    {
        int curNum = 0 ;
        do{
            curNum = rand() % range +1;
        }while(set.find(curNum)!=set.end());
        set.insert(curNum);
        numkinds--;
        for(int i=0;i<m;i++)
        {
            v[index++]=curNum;
        }
    }
    // v 填好了
    // 由于数据太整齐了,我们打乱数据
    for(int i=0;i<v.size();i++)
    {
        int j = rand() % v.size() ; // 0 ~ size-1;
        int tmp = v[i];
        v[i]=v[j];
        v[j]=tmp;
    }
    return std::move(v);
}
// 对数器
void test2()
{
    srand((int)time(NULL));
    int kinds = 100;         // 元素种类 1~ 100
    int range = 300;        // 元素范围 1~300
    int testTime = 1000; // 测试次数
    int max = 9;           // k,m 范围 1~9
    cout << "测试开始\n";
    while (testTime--)
    {
        int a = rand()%max + 1;
        int b = rand()%max + 1;
        int k = std::min(a,b);
        int m = std::max(a,b);
        if(k==m){
            m++;
        }


        vector<int> v = randomArray(kinds, range, k, m);
        int ans1 = onlyKTimes(v, k, m);
        int ans2 = testonlyKTimes(v, k, m);
        if (ans1 != ans2)
        {
            cout << "出错了\n";
        }
    }
    cout << "测试结束\n";
}
int main()
{
    test2();
}

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

相关文章:

  • 微搭低代码入门05循环
  • Vue3中一级导航栏的吸顶导航交互以及Pinia优化重复请求
  • Uniapp踩坑input自动获取焦点ref动态获取实例不可用
  • 林曦词典|养生
  • 前端学习八股资料CSS(二)
  • 【代码审计】常见漏洞专项审计-业务逻辑漏洞审计
  • 人不成熟的五大特征-读后感
  • 后端程序员的前端必备【Vue】 - 04 Vue监听属性、计算属性、过滤器(全局过滤器和局部过滤器)
  • NPN三极管放大原理
  • 适合学生党的蓝牙耳机品牌有哪些?学生性价比高的蓝牙耳机排行
  • ChatGPT技术原理 第四章:Transformer模型
  • MySQL用户管理
  • 云计算基础(持续更新)
  • 【软件测试】项目测试—MySQL数据库操作应用场景?必会知识详全(超详细)
  • 术数基础背诵口诀整理
  • 小红书流量密码是什么,怎么掌握并运用
  • 定时每天凌晨一点在linux系统上执行一个autobuild.sh脚本如何实现?
  • Keep your direction
  • 软件工程导论 - 了解黑盒测试
  • 使用多模态数据映射大脑网络
  • 3dMax需要什么样的硬件环境才能更好的工作?
  • 【配电网优化】基于串行和并行ADMM算法的配电网优化研究(Matlab代码实现)
  • 微服务架构编码构建
  • 【高危】Apache Superset <2.1.0 认证绕过漏洞(POC)(CVE-2023-27524)
  • linux常用命令大全(保姆及入门)
  • main.m文件解析--@autoreleasepool和UIApplicationMain