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

news2025/2/26 14:22:17

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 int
        int 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 int
        
        for (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 int
        for (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.coloradmin.cn/o/1148362.html

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

相关文章

微信小程序 人工智能志愿者服务活动报名系统uniAPP+vue

基于java语言设计并实现了人工智能志愿者服务APP。该APP基于B/S即所谓浏览器/服务器模式&#xff0c;应用SpringBoot框架与HBuilder X技术&#xff0c;选择MySQL作为后台数据库。系统主要包括用户、志愿活动、活动报名、活动签到、服务职责、服务排行等功能模块。 本文首先介绍…

C++之回调函数使用和不使用using、typedef、function定义总结(二百五十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

prometheus服务发现

Consul简介 ◼ 一款基于golang开发的开源工具&#xff0c;主要面向分布式&#xff0c;服务化的系统提供服务注册、服务发现和配置管理 的功能 ◼ 提供服务注册/发现、健康检查、Key/Value存储、多数据中心和分布式一致性保证等功能 部署 curl -LO https://releases.hashicorp…

单片机与进制数

目录 一:数字系统的由来 A:二进制 1: 基础概念 2: 二进制运算 3:二进制的计算 B:八进制 1:基础概念 C:16进制表 四:单片机中的进制数 一:数字系统的由来 1:远古时代:结绳计数 2:非位置化数字系统: 罗马数字 非位置化数字系统: 一个符号在不同的位置只会表达同样的意思…

Gitee 发行版

Gitee 发行版 1、Gitee 发行版管理2、项目仓库中创建发行版本3、项目中导入3.1 gradle配置3.2 dependencies执行正常&#xff0c;包没有下载 1、Gitee 发行版管理 Gitee 发行版&#xff08;Release&#xff09;管理 2、项目仓库中创建发行版本 按照Gitee官网操作就行 3、项目…

N-130基于springboot,vue校园社团管理系统

开发工具&#xff1a;IDEA 服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8 项目构建&#xff1a;maven 数据库&#xff1a;mysql5.7 系统分前后台&#xff0c;项目采用前后端分离 前端技术&#xff1a;vueelementUI 服务端技术&#xff1a;springbootmybatis-plus 本系…

Linux 下 12 个最佳 Notepad++ 替代品

Notepadd 是一款完全免费的源代码编辑器&#xff0c;旨在替代 Windows 上的记事本 – 基于 Scintilla 用 C 编写&#xff0c;并实现 Win32 API 和 STL&#xff0c;以确保程序尺寸小且执行速度快 – 这些特性使其成为一个家族开发者中的名字。遗憾的是&#xff0c;没有适用于 Li…

Jetpack:021-Jetpack中的滑动列表

文章目录 1. 概念介绍2. 使用方法2.1 函数参数2.2 列表成员 3. 示例代码4. 内容扩展5. 内容总结 我们在上一章回中介绍了Jetpack中底部导航栏相关的内容&#xff0c;本章回中主要介绍 滑动列表。闲话休提&#xff0c;让我们一起Talk Android Jetpack吧&#xff01; 1. 概念介绍…

【Git】HEAD detached from xxx 问题及解决方案

问题背景 最近用git的时候遇到了一个问题&#xff0c;场景是这样的。 我有一个分支main&#xff0c;其中有两个commit A和B&#xff0c;A是最新commit&#xff0c;B是历史commit。我先切到B看了看之前的代码&#xff0c;然后切到A&#xff0c;并进行了一些代码修改&#xff0…

H5游戏源码分享-跑酷游戏熊出没

H5游戏源码分享-跑酷游戏熊出没 <!DOCTYPE html> <html manifest"manifest.mf"><head><meta http-equiv"Content-Type" content"text/html; charsetUTF-8"><meta http-equiv"Content-Type" content"…

一、灵动mm32单片机_开发环境的搭建(Keil)

1、安装Keil MDK。 略。 2、安装芯片对应的Pack包。 (1)这里以MM32F0130单片机为例。 (2)进入灵动微电子官网。上海灵动微电子股份有限公司 (3)点击“支持”→“KEILPacl”。 (3)点击下载Pack包。 (4)下载后&#xff0c;解压下载的压缩包&#xff0c;找到对应的Pack包&…

PostgreSQL InvalidMessage Cache 同步机制

文章目录 背景InvalidMessages 基本类型InvalidMessages 数据结构概览共享内存 的 "ring-buffer" 结构Backend 本地的 InvalidMessages管理SharedInvalCatalogMsgSharedInvalCatcacheMsgSharedInvalRelcacheMsgSharedInvalSnapshotMsgSharedInvalSmgrMsgSharedInvalR…

【C++深入浅出】模版初识

目录 一. 前言 二. 泛型编程 三. 函数模版 3.1 函数模版的概念 3.2 函数模版的格式 3.3 函数模版的原理 3.4 函数模板的实例化 3.5 模板参数的匹配原则 四. 类模版 4.1 类模版的定义 4.2 类模版的实例化 一. 前言 本期我们要介绍的是C的又一大重要功能----模版。通…

DIY相机(一)libcamera库

相机选型 DIY相机首先是要确定使用的相机型号。兼容树莓派&#xff0c;画质好一些的&#xff0c;目前主要有两款&#xff1a;一是Raspberry Pi Camera Module 3&#xff0c;二是Raspberry Pi HQ Camera。 下图是Raspberry Pi Camera Module 3的相关特性。支持自动对焦和HDR等…

opencv dnn模块 示例(20) 目标检测 object_detection 之 yolor

文章目录 1、论文介绍1.1、YOLOR思想动机1.2、隐式知识学习1.2.1、隐式知识如何工作1.2.2、隐式知识统一网络建模 1.3、实验1.4、总结 2、测试2.1、opencv dnn2.1.1、代码2.1.2、结果 2.2、测试效率 YOLOR出自论文You Only Learn One Representation: Unified Network for Mult…

【mfc/VS2022】计图实验:绘图工具设计知识笔记3

实现类对串行化的支持 如果要用CArchive类保存对象的话&#xff0c;那么这个对象的类必须支持串行化。一个可串行化的类通常有一个Serialize成员函数。要想使一个类可串行化&#xff0c;要经历以下5个步骤&#xff1a; 1、从CObject派生类 2、重写Serialize成员函数 3、使用DE…

【计算机网络 】传输层——UDP

目录 传输层传输层概念再谈端口号协议号和端口号端口号区域常见端口号pidof UDPUDP协议格式UDP协议的特点UDP的缓冲区UDP传输数据注意事项 传输层 传输层概念 在学习HTTP等应用层协议时&#xff0c;为了便于理解&#xff0c;可以简单的认为HTTP协议是将请求和响应直接发送到了…

​​​​​​​为什么你的Word文件无法移动到U盘

为什么你的Word文件无法移动到U盘 你是否遇到过这样的情况&#xff1a;你在苹果电脑上编辑了一个Word文档&#xff0c;想要把它拷贝到一个U盘上&#xff0c;但是却发现无法操作。你可能会感到很奇怪&#xff0c;为什么你的Word文件无法移动到U盘呢&#xff1f;这是因为苹果电脑…

ESM蛋白质语言模型系列

模型总览 第一篇《Biological structure and function emerge from scaling unsupervised learning to 250 million protein sequences 》ESM-1b 第二篇《MSA Transformer》在ESM-1b的基础上作出改进&#xff0c;将模型的输入从单一蛋白质序列改为MSA矩阵&#xff0c;并在Tran…

TensorRT量化实战课YOLOv7量化:pytorch_quantization介绍

目录 前言1. 课程介绍2. pytorch_quantization2.1 initialize函数2.2 tensor_quant模块2.3 TensorQuantizer类2.4 QuantDescriptor类2.5 calib模块 总结 前言 手写 AI 推出的全新 TensorRT 模型量化实战课程&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考。 该…