C++【面试重要题目】 只出现一次的数字的集合.

news2024/11/23 20:42:43

文章目录

  • 前言
  • 一、前提要点补充
  • 二、题集
  • 总结


前言

本篇笔者将会对 cpp 中比较有意思的类型题目进行细致讲解 . 这类题同时也是面试中比较重要的算法题 , 其算法思想需要学者掌握.

以下题目均来自力扣


一、前提要点补充

几个运用运算符

因为笔者介绍的题目均会用到二进制相关知识 , 所以涉及一些操作符的知识 , 以下给出补充 !

& (按位与)

作用 : 本操作符通常用于提取 或 检查某些特定的二进制位.

规则 : 记忆法 – 两个都为真才为真

两个位都为 1 时 , 结果为 1

有一个位为 0 时 , 结果为 0

代码介绍

#include <iostream>
using namespace std;

//按位& 操作符
// & --- 一般用于提取 \ 检查 二进制位
int main()
{
	int a = 3;
	//二进制: 32位 , 这里笔者省略写 -----  0011 - 3

	//判断最低位比特位是 0 还是 1 ?

	//对最低位进行标志 , 要判断最低位这里我们的思路就是将该数 & 1 , 因为1的二进制是 0001
	int maska = a & 1; // 0011 & 0001 ---- 0001 - 1
	
	if (maska == 0)
		cout << "0" << endl;
	else
		cout << maska << endl;
	return 0;
}

| (按位或)

作用 : 本操作符通常用于设置某些特定的二进制位 , 也常用于二进制位恢复整数的操作.

规则 : 记忆法 – 一个为真就为真

两个位都为 0 时 , 结果为 0

有一个位为 1 时 , 结果为 1

代码介绍

#include <iostream>
using namespace std;


int main()
{
	int a = 2;
	//二进制: 32位 , 这里笔者省略写 -----  0010 - 2
	
	//将该数的最低位比特位置为 1 
	
	//因为要给最低位赋值,我们考虑用 | , 但是一般都是和 1结合,因为1的二进制位是 0001
	int maska = a | 1; // 0010 | 0001 ---- 0011 - 3
	
	//输出
	cout << maska << endl;
	return 0;
}

重点总结 : 一般 & 可以用来提取进制位 , | 用于复原操作位 .


^ (异或)

作用 : 可以用于数字的消除

规则 :

两个位相同时 , 结果为 0 ----- 相同为0

两个位不同时 , 结果为 1 ----- 相异为1

0 ^ 任何数都为它本身

满足交换律

代码介绍

#include <iostream>
using namespace std;


int main()
{
	int a = 1;
	int b = 2;
	int c = 1;
	
	int ret = a ^ b ^ c;
	// 1 ^ 2 ^ 1 -- 满足交换律 -- 1 ^ 1 ^ 2 -- 0 ^ 2 -- 2
	cout << ret << endl;
	return 0;
}

▶ 面试题

不创建第三个变量, 完成两个变量的交换.

题目中要求不创建第三个变量 , 还要完成交换 , 以我们常规的思路 , 交换变量就是依靠一个临时变量 ,但这个思路就被 Pass 掉了 , 所以这里就引出了一个新的思路 , 用 ^ 操作符.

#include <iostream>
using namespace std;


int main()
{
	int a = 1;
	int b = 2;
	cout << "交换前 a : " << a << endl;
	cout << "交换前 b : " << b << endl;
	
	a = a ^ b;  // a = 1 ^ 2 
	b = a ^ b;  // b = a ^ b ^ b = a
	a = a ^ b;  // a = a ^ a ^ b = b
	
	cout << "交换后 a : " << a << endl;
	cout << "交换后 b : " << b << endl;
	return 0;
}

<< 和 >> (左移操作符和右移操作符)

这里注意与流提取和流插入操作符区分 , 当涉及二进制时 , 这里的 << \ >> 就代表了用于进制的 左移 和 右移了.

左移操作符

规则 : 左边抛弃 , 右边补 0

右移操作符

右移分为两种 : 逻辑右移 , 算术右移.

逻辑右移 : 左边用 0 填充个 , 右边直接抛弃.

算术右移 : 左边用原该数值的符号位填充 , 右边直接丢弃.

区分 那么什么时候用逻辑右移 , 什么时候用算术右移呢 ?

可以发现 , 逻辑右移与数值的符号无关.

故:

当处理无符号数时 , 用逻辑右移

当处理有符号数时 , 用算术右移


以上就是基本知识的铺垫 : 如下为本篇重要内容 , 题目均可点击跳转 .

二、题集

只出现一次的数字 |

只出现一次的数字 ||

只出现一次的数字 |||

讲解

只出现一次的数字 |

这里笔者就不附图片了 , 直接对本题进行描述 .

本题的要求很简单 : 只有一个数字出现一次 , 其余均出现两次 , 要求 : 返回只出现一次的元素.

▶ 算法思路

抓住题中字眼 : 两次

关于两次 , 我们可以考虑一种思路就是用二进制 , 目的是对出现两次的数字消除 , 只留下出现一次的数字.这个思路

正好符合 ^ 操作符的规则 , 相同异或为0 , 不同的为1 , 0 ^ 任何数都为自己.

▶ OJ代码

class Solution {
    //依据题 , 只有一个数字出现一次 ,其余出现两次 ,考虑用 ^
public:
    int singleNumber(vector<int>& nums) {
        
        int res = 0;
        //把所有元素异或就是出现一次的元素
        for(auto e: nums)
        {
            res ^= e;
        }

        // 此时的 res 就是出现一次的那个数字
        return res;
    }
};

只出现一次的数字 ||

明显的可以看到本题的难度有所上升 , 但要是说通过该题那就是相当容易了, 直接一个暴力遍历也可解决问题 , 但这里笔者给出新的思路.

▶ 算法思路

依据 只出现一次的数字 | 题的思想 , 用二进制 , 那么本题也同样 , 可以用二进制的思想来进行.

首先 : 题目是 : 只有一个数字出现一次 , 其余数字出现三次 , 如果单纯的用 ^ 就会返现不可行了.

因为异或操作符的本质就是 % 2 .

抓题目字眼 : 三次 , 那么怎么对这个 下手 , 只留下 一 呢 ?

不妨这样想:
● 对于出现三次的数字来说 , 要转化成其二进制 , 二进制都是 0 \ 1 组成 , 那么把这些元素的二进制对应的二进制位相加 , 则 : 对应位的和一定是 3 的倍数(即 : %3 == 0).
但当加入出现一次的数字后 , 其在某一比特位上是 0 , 则不会对该比特位上的和有影响 , 但当该比特位是 1 时就对该比特位的和有影响了, 则 : 这个比特位对应的数就是 %3 的余数了.

举例 : nums = [2,2,3,2]

在这里插入图片描述
▶ OJ代码

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        
        //用于存放出现一次的数
        int res = 0;

        //判断对应位二进制的和是否为3的倍数
        for(int i = 0; i < 32 ; ++i)
        {
            int count = 0; //记录每一个对应比特位的和
            for(auto e: nums)
            {
                //这里涉及得到每一个二进制位,根据笔者之前的前提知识结论,一般 & 是提取二进制位,都是与 1相关
                //故可以思考方向如下: 每一位对应的二进制位 & 1 就是对应的该位的二进制位
                //例如: 2 ---- 0010 , 要得到 2 的第0位
                //      (2 >> i) & 1 , (i = 0,1,2,3,4...32),这样可以得到2的每一位
                //      当 i = 0 时, 0010 >> 0 -- 0010 & 0001 --- 0000 -- 0(i = 0,时该位为0)
                //      当 i = 1 时, 0010 >> 1 -- 0001 & 0001 --- 0001 -- 1(i = 1,时该位为1) 
                count += (e >> i) & 1;
            }

            //判断对应位二进制的和是否为3的倍数
            if(count % 3) // != 0 , 证明该位属于出现一次数字的第 i 位比特位
            {
                 //那么就要把第 i 位置为1,,即笔者前提知识结论,一般 | 是可以给对应二进制位赋值
                 // 1 << i --- 把第 i 位变成 1
                 res |= 1 << i; 
                 // i = 0 , 1 << 0 --- 0001 --- 1 , 第1位为1
                 // i = 1 , 1 << 1 --- 0010 --- 2 , 第2位为1
            }
        }
        return res;
    }
};

只出现一次的数字 |||

▶ 算法思路

本题又是第一题的变题.

题目描述: 恰好有两个元素只出现一次,其余所有元素均出现两次。要求: 返回出现两次的两个数.

● 本题除了出现两次的两个数以后 , 其余均出现两次 , 这我们可以考虑 ^ 操作符 将出现两次的数全部抵消.
● 思路转化为 :异或全部元素 , 这样就把出现两次的元素全部异或掉了 , 那么最后一次的异或就是出现一次
的两个数进行异或.

● 但我们的目的是找出现一次的两个数 , 在进行一次全部异或操作后把两个出现一次的元素异或成了一个值.
这时就要想办法把这两个值还原出来.

在这里插入图片描述

● 那么要区分两个数就要把两个数分为两组 .

在这里插入图片描述

▶ OJ代码

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        
        int xoxALL = 0;
        //对所以元素进行异或,最后一次的异或就是两个出现一次的数的异或操作
        for(auto e :nums)
        {
            xoxALL ^= e;
        }

        //xoxALL 为最后一次异或的结果,进行区分标志
        //例如: 3 , 5要区分的位置是第2位,要得到第2位一般考虑 &
        // xoxALL = 6 , -xoxALL = -6;
        // 0110 - 6
        //~0110+1 -- 1001+1 -- 1010 --- -6
        // 0110 & 1010 --- 0010 - 2
        //判断溢出:当 xoxALL 为INT_MIN 时,对其取反 + 1就超过了整型表达范围了
        int mask = (xoxALL == INT_MIN) ? INT_MIN: xoxALL & (-xoxALL);

        //判断
        int type1 = 0 , type2 = 0;
        for(auto e:nums)
        {
            if(e & mask) // !=0 为一组
                type1 ^= e;
            else
                type2 ^= e;
        }

        return {type1,type2};
    }
};

总结

以上为只出现一次的数字的题目集合 , 是比较重要的题目 ,希望学者认真理解 !

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2246233.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

麒麟部署一套NFS服务器,用于创建网络文件系统

一、服务端共享目录 在本例中,kyserver01(172.16.200.10)作为客户端,创建一个目录/testdir并挂载共享目录;kyserver02(172.16.200.11)作为服务端,创建一个共享目录/test,设置为读写权限,要求客户端使用root登录时映射为nobody用户、非root登录时保持不变。 服务端启…

VBA技术资料MF228:移动形状并覆盖某单元格区域

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

Python 数据分析核心库大全!

&#xff08;欢迎关注我的视频号&#xff09; &#x1f447;我的小册 45章教程:(小白零基础用Python量化股票分析小册) ,原价299&#xff0c;限时特价2杯咖啡&#xff0c;满100人涨10元。 大家好&#xff01;我是菜鸟哥&#xff01; 今天我们来聊点干货&#xff1a;Python 数据…

跨境出海安全:如何防止PayPal账户被风控?

今天咱们聊聊那些让人头疼的事儿——PayPal账户被风控。不少跨境电商商家反馈&#xff0c;我们只是想要安安静静地在网上做个小生意&#xff0c;结果不知道为什么&#xff0c;莫名其妙账户就被冻结了。 但其实每个封禁都是有原因的&#xff0c;今天就来给大家分享分享可能的原…

39页PDF | 毕马威_数据资产运营白皮书(限免下载)

一、前言 《毕马威数据资产运营白皮书》探讨了数据作为新型生产要素在企业数智化转型中的重要性&#xff0c;提出了数据资产运营的“三要素”&#xff08;组织与意识、流程与规范、平台与工具&#xff09;和“四重奏”&#xff08;数据资产盘点、评估、治理、共享&#xff09;…

数据科学与SQL:组距分组分析 | 区间分布问题

目录 0 问题描述 1 数据准备 2 问题分析 3 小结 0 问题描述 绝对值分布分析也可以理解为组距分组分析。对于某个指标而言&#xff0c;一个记录对应的指标值的绝对值&#xff0c;肯定落在所有指标值的绝对值的最小值和最大值构成的区间内&#xff0c;根据一定的算法&#x…

使用 PyTorch-BigGraph 构建和部署大规模图嵌入的完整教程

当涉及到图数据时&#xff0c;复杂性是不可避免的。无论是社交网络中的庞大互联关系、像 Freebase 这样的知识图谱&#xff0c;还是推荐引擎中海量的数据量&#xff0c;处理如此规模的图数据都充满挑战。 尤其是当目标是生成能够准确捕捉这些关系本质的嵌入表示时&#xff0c;…

23种设计模式-模板方法(Template Method)设计模式

文章目录 一.什么是模板方法模式&#xff1f;二.模板方法模式的特点三.模板方法模式的结构四.模板方法模式的应用场景五.模板方法模式的优缺点六.模板方法模式的C实现七.模板方法模式的JAVA实现八.代码解析九.总结 类图&#xff1a; 模板方法设计模式类图 一.什么是模板方法模…

.net的winfrom程序 窗体透明打开窗体时出现在屏幕右上角

窗体透明&#xff0c; 将Form的属性Opacity&#xff0c;由默认的100% 调整到 80%(尽量别低于50%)&#xff0c;这个数字越小越透明&#xff01; 打开窗体时出现在屏幕右上角 //构造函数 public frmCalendarList() {InitializeComponent();//打开窗体&#xff0c;窗体出现在屏幕…

DRNN 神经网络的Jacobian 信息辨识

DRNN 神经网络的 Jacobian 信息辨识 1. 基本原理 Jacobian 矩阵用于描述多输入多输出系统中输入和输出之间的偏导关系&#xff0c;其形式为&#xff1a; 对于 DRNN&#xff08;Dynamic Recurrent Neural Network&#xff09;&#xff0c;其动态特性使得 y(t)\mathbf{y}(t)y(t…

iptables网络安全服务详细使用

iptables防火墙概念说明 开源的基于数据包过滤的网络安全策略控制工具。 centos6.9 --- 默认防火墙工具软件iptables centos7 --- 默认防火墙工具软件firewalld&#xff08;zone&#xff09; iptables主要工作在OSI七层的二、三、四层&#xff0c;如果重新编译内核&…

《DAMA 数据管理知识体系指南》读书笔记 - 第 2 章 数据处理伦理

文章目录 1. 章节概述2. 核心概念与定义3. 重要方法与实践步骤4. 理论与实际结合5. 重点6. 理解与记忆要点7. 复习思考题标题图——书籍图片 WPS AI生成的XMind链接&#xff08;不用要源文件&#xff0c;下载不了&#xff09;&#xff1a; 【金山文档 | WPS云文档】 第2章 数据…

《线性代数的本质》

之前收藏的一门课&#xff0c;刚好期末复习&#xff0c;顺便看一看哈哈 课程链接&#xff1a;【线性代数的本质】合集-转载于3Blue1Brown官方双语】 向量究竟是什么 线性代数中最基础、最根源的组成部分就是向量&#xff0c;需要先明白什么是向量 不同专业对向量的看法 物理专…

AI 大模型如何重塑软件开发流程?——技术革新与未来展望

人工智能的蓬勃发展为许多领域注入了强劲动力&#xff0c;而在软件开发这一关键技术领域&#xff0c;AI 大模型的应用正在彻底改变传统流程。从代码自动生成到智能测试&#xff0c;再到协同开发和流程优化&#xff0c;AI 正逐步成为软件开发者的得力助手&#xff0c;也推动企业…

三季度业绩亮点多元,宝尊全域经营走向破茧成蝶

电商行业的变革从未停止&#xff0c;始终反映着网络消费和品牌发展的趋势&#xff0c;以及未来的想象空间&#xff0c;因此令赛道上的相关公司备受关注。 那么&#xff0c;当前赛道正在发生哪些变化&#xff1f;11月21日&#xff0c;行业龙头宝尊电商发布截至2024年9月30日的2…

机器学习day7-线性回归3、逻辑回归、聚类、SVC

7欠拟合与过拟合 1.欠拟合 模型在训练数据上表现不佳&#xff0c;在新的数据上也表现不佳&#xff0c;常发生在模型过于简单无法处理数据中的复杂模式时。 特征&#xff1a; 训练误差较高 测试误差也高 模型过于简化&#xff0c;不能充分学习训练数据中的模式 2.过拟合 …

【云计算】腾讯云架构高级工程师认证TCP--考纲例题,知识点总结

【云计算】腾讯云架构高级工程师认证TCCP–知识点总结&#xff0c;排版整理 文章目录 1、云计算架构概论1.1 五大版块知识点&#xff08;架构设计&#xff0c;基础服务&#xff0c;高阶技术&#xff0c;安全&#xff0c;上云&#xff09;1.2 课程详细目录1.3 云基础架构设计1.4…

proto3语法详解

proto3语法详解 字段规则消息类型的定义与使⽤定义使用 enum类型定义与使用定义规则定义时注意事项 Any类型Any类型介绍Any类型使用 oneof类型oneof类型的介绍oneof类型的使用 map类型map类型的介绍map类型的使用 默认值更新消息更新规则保留字段reserved 未知字段未知字段获取…

【STM32】在 STM32 USB 设备库添加新的设备类

说实话&#xff0c;我非常想吐槽 STM32 的 USB device library&#xff0c;总感觉很混乱。 USB Device library architecture 根据架构图&#xff1a; Adding a custom class 如果你想添加新的设备类&#xff0c;必须修改的文件有 usbd_desc.cusbd_conf.cusb_device.c 需要…

怎么编译OpenWrt镜像?-基于Widora开发板

1.准备相应的环境&#xff0c;我使用的环境是VMware16ubuntu20.04&#xff0c;如图1所示安装编译所需的依赖包&#xff1b; sudo apt-get install build-essential asciidoc binutils bzip2 gawk gettext git libncurses5-dev libz-dev patch python3 python2.7 unzip zlib1g-…