leetCode 260.只出现一次的数字 ||| + 位运算

news/2025/3/5 5:57:21/

260. 只出现一次的数字 III - 力扣(LeetCode)


给你一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。你必须设计并实现线性时间复杂度的算法且仅使用常量额外空间来解决此问题。


【问题思考】待解决问题(O_O)?举个栗子:xorSum -> 110,需要找到异或和中的某个值为 1 的比特位,如何解决?

  • 方式1:计算 lowbit ,只保留二进制最低位的1举个栗子
 s = 101100
~s = 010011 
(~s)+1 = 010100 // 根据补码的定义,这就是-s 最低 1 左侧取反,右侧不变
s & -s = 000100 // lowbit

  • s 和 ~s 若相与,为0

【求补码】:(~s)+ 1,可以简易操作成,其实就是从~s(取反)的结果上,从左到右,直到找到一个0后面都是连续1的子序列的位置,将其设置为1,而后面连续的1的子序列全置为0。这是求补码这个过程。然后再让 s & (~s+1) 就可以获得lowbit。

【问题思考(O_O)?】为什么s & (~s+1) 就可以获得 lowbit?原理是什么?

结合上图来看,在取反的结果(~s)上找从左到右出现 0 的最低位位置,而这个位置的左边仍然是保持 s 取反后的结果,也就是和 s 相与还是为0。那我们将 ~s这个位置设置为 1其后的设置为 0,那么 s & (~s+1) 自然就可以找到 s 出现 1 的最低位置,也就可以获得lowbit了。(因为你找到取反后的结果的 0 出现的最低位置,那么就可以通过运算变换求出 s 出现 1 的最低位置,而这恰好有求补码的过程,那么我们也可以进一步将求补码的过程简洁写成 -s )。具体操作如下:

  • ① 求补码
  • s & s的补码 => lowbit,即 s & (~s + 1)

【一个有意思的点】根据补码的定义,就是 -s,那么

  • s & (-s) => lowbit

  • 方式2:计算 s尾零的个数,直接取 nums[i] 在该比特位上的值,从而避免逻辑判断

 (1)根据 方式1:计算 lowbit ,只保留二进制最低位的1

class Solution {
public:vector<int> singleNumber(vector<int>& nums) {vector<int>res;unsigned int xorSum = 0; //C++ 不需要防止溢出,用 unsigned intint type1=0,type2=0;for (const int &num: nums) {xorSum ^= num;}// -xorSum 等价于 对xorSum求补码,操作就是取反后加一// int lowbit = xorSum & (~xorSum+1);int lowbit = xorSum & -xorSum; for (const int &num: nums) {//进行分组//把值为1的数分为一组if(num & lowbit) type1^=num;//把值为0的数分为一组else type2^=num;}return {type1, type2};}
};

 用一个vector容器来存放 type1 和 type2,也可以省去逻辑判断(if...else...)

        ......int type1=0,type2=0;int lowbit = xorSum & -xorSum; for (const int &num: nums) {if(num & lowbit) type1^=num; //把值为1的数分为一组else type2^=num; //把值为0的数分为一组}return {type1, type2};}
};
-------------------------------------------------------------------------------------......vector<int> arr(2);for (const int &num: nums) {arr[(num & lowbit)!=0] ^=num; // (num & lowbit)!=0 => true(1) or false(0)}return arr;}
};

于是就有如下代码: 

class Solution {
public:vector<int> singleNumber(vector<int>& nums) {unsigned int xorSum = 0; //C++ 不需要防止溢出,用 unsigned intfor (const int &num: nums) {xorSum ^= num;}// -xorSum 等价于 对xorSum求补码,操作就是取反后加一// int lowbit = xorSum & (~xorSum+1);int lowbit = xorSum & -xorSum; vector<int> arr(2);for (const int &num: nums) {arr[(num & lowbit)!=0] ^=num; // (num & lowbit)!=0 => true(1) or false(0)}return arr;}
};

(2)根据方式2:计算 s尾零的个数,直接取 nums[i] 在该比特位上的值,从而避免逻辑判断

C++ __builtin_系列函数___builtin_ctz-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/yandaoqiusheng/article/details/102920785__builtin_ctz(x) : 返回 x 的二进制下前导的 0 的个数

class Solution {
public:vector<int> singleNumber(vector<int>& nums) {unsigned int xorSum = 0; //C++ 不需要防止溢出,用 unsigned intfor (const int &num: nums) {xorSum ^= num;}int ctz = __builtin_ctz(xorSum);vector<int> arr(2);for (const int &num: nums) {arr[(num >> ctz) & 1] ^=num; }return arr;}
};
  • 时间复杂度:O(n),其中 n 为 nums 的长度
  • 空间复杂度:O(1),仅用到若干额外变量

参考和推荐文章:

260. 只出现一次的数字 III - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/single-number-iii/solutions/2484352/tu-jie-yi-zhang-tu-miao-dong-zhuan-huan-np9d2/分享|从集合论到位运算,常见位运算技巧分类总结! - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/circle/discuss/CaOJ45/


http://www.ppmy.cn/news/1184751.html

相关文章

k8s day10

JENKINS集成K8S项目实战 部署Jenkins环境: 1.下载Jenkins软件包 curl -o jenkins-k8s.zip http://192.168.17.253/Kubernetes/day10-/softwares/jenkins-k8s.zip 2.解压软件包 yum -y install unzip unzip jenkins-k8s.zip 3.安装JDK环境&#xff0c;如上图所示 cd jenki…

【JavaSE】运算符详解及与C语言中的区别

在文章的最后&#xff0c;总结了Java与C语言的某些不同点 目录 一、什么是运算符 二、算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符/-- 三、关系运算符 四、逻辑运算符&#xff08;重点&#xff09; 1.逻辑与&& 2.逻辑或|| 3.逻辑非 4.补…

RK3588开发笔记-USB3.0接口调试

目录 前言 一、资源介绍 二、硬件连接 三、设备树配置

假如我有一台服务器,我会让它提供三种服务

一、提供照片上传、存储和下载服务 随着移动互联网时代的持续快速发展&#xff0c;PC互联网日益势微&#xff0c;各大互联网门户网站的博客、空间也跟着凋零&#xff0c; 作为博客、空间的标配功能的相册也随之被关闭。 2019年3月6日网易相册发布停运公告并于当年5月8日正式停…

LeetCode 541 反转字符串 II 简单

题目 - 点击直达 1. 541 反转字符串 II 简单1. 题目详情1. 原题链接2. 题目要求3. 基础框架 2. 解题思路1. 思路分析2. 时间复杂度3. 代码实现 1. 541 反转字符串 II 简单 1. 题目详情 给定一个字符串 s 和一个整数 k&#xff0c;从字符串开头算起&#xff0c;每计数至 2k 个…

腾讯云2023年双11活动:云服务器2核2G首年88元,领券最高省9999元!

双11作为全球最大的购物狂欢节&#xff0c;云计算行业也将迎来一场盛大的活动。腾讯云作为云计算领域的领先者&#xff0c;2023年双11期间推出了一系列超值优惠活动&#xff0c;本文将为大家介绍腾讯云2023年11.11云上盛惠活动的亮点和优惠内容。 一、活动地址 活动入口&#…

Epinoia-有状态网络的意图验证模块,略读

Epinoia relies on a unified model for NFs by leveraging the causal precedence relationshipsthat exist between NF packet I/Os and states. 这句话的意思是&#xff1a;“Epinoia依靠一种统一的网络功能&#xff08;NF&#xff09;模型&#xff0c;通过利用存在于 NF 包…

LV.12 D11 FS4412开发环境搭建 学习笔记

开发板硬件资源介绍 初识电路原理图 元器件查找 1.搜索丝印 2.查找目录 网络标号 电路图中网络标号相同的节点在电气上是连接在一起的 交叉开发环境搭建 1.在ubuntu下安装交叉编译工具链 2.在windows下安装SecureCRT 3.在windows下安装USB转串口驱动…