1.题目介绍

2.题解

2.1 快排+遍历

思路

同本系列前几题一样

代码

class Solution {
public:
std::vector<int> singleNumber(std::vector<int>& nums) {
int count = 0;
std::vector<int> arr;
std::sort(nums.begin(),nums.end());
for (int i = 0; i < nums.size(); i++) {
if (i == nums.size() - 1 && count == 0) {
arr.push_back(nums[i]);
if (arr.size() == 2) return arr;
};
if (nums[i] == nums[i+1]) count++;
else if(count) count = 0;
else {
arr.push_back(nums[i]);
if (arr.size() == 2) return arr;
}
}
return arr;
}
};

复杂度分析

  • 时间复杂度:

    排序阶段的时间复杂度为 \(O(nlog_n)\),其中 n 是输入数组的长度。

    查找单独出现数字的阶段是一个线性扫描,时间复杂度为 O(n)。

    总体来说,代码的时间复杂度为 \(O(nlog_n) + O(n) = O(nlog_n)\)。

  • 空间复杂度:

    代码的空间复杂度为 O(1)。

2.2 哈希表(牺牲空间)

思路

设计(数字,出现次数)的键值对,使用哈希表进行存储

代码

class Solution {
public:
std::vector<int> singleNumber(std::vector<int>& nums) {
std::vector<int> arr;
std::unordered_map<int, int> map;
for (int num: nums){
map[num]++;
}
for (const auto& [num, occ]: map){
if (occ == 1) arr.push_back(num);
}
return arr;
}
};

复杂度分析

  • 时间复杂度:O(n),其中 n 是数组 nums的长度。
  • 空间复杂度:O(n),即为哈希映射需要使用的空间。

2.3 位运算(分治算法)

思路

假设数组 nums 中只出现一次的元素分别是x1和x2,如果把 nums中的所有元素全部异或起来,得到结果 x,那么一定有:\(x=x_1\oplus x_2\)

x显然不会等于 0,因为如果 \(x=0\) , 那么说明 \(x_1=x_2\) ,这样 \(x_1\) 和 \(x_2\) 就不是只出现一次的数字了。

因此,我们可以使用位运算 \(x \& -x\) 取出 \(x\) 的二进制表示中最低位那个 1, 设其为第\(l\) 位, 那么 \(x_1\) 和 \(x_2\) 中的某一个数的二进制表示的第 \(l\) 位为 0, 另一个数的二进制表示的第 \(l\) 位为 1。在这种情况下, \(x_1\oplus x_2\) 的二进制表示的第 \(l\) 位才能为 1。

(在计算机中,负整数通常以其二进制补码的形式表示。负数的补码是通过将其对应的正数的二进制表示取反(按位取反,0变1,1变0),然后再加1得到的。

例如,-3 的二进制补码表示是 \(11101\)。3的二进制原码和补码均是 \(00011\), \(3 \& (-3) = 00001\))

这样一来,我们就可以把 \({nums}\) 中的所有元素分成两类,其中一类包含所有二进制表示的第 \(l\)位为 0 的数, 另一类包含所有二进制表示的第 \(l\) 位为 1 的数。可以发现:

  • 对于任意一个在数组 \(nums\) 中出现两次的元素, 该元素的两次出现会被包含在同一类中;
  • 对于任意一个在数组 \(nums\) 中只出现了一次的元素, 即 \(x_1\) 和 \(x_2\), 它们会被包含在不同类中。

这里其实就是一种分治算法的思想,将所有数组成员分为两组,并且分别处理

代码

class Solution {
public:
std::vector<int> singleNumber(std::vector<int>& nums) {
int res = 0;
int temp1 = 0, temp2 = 0;
std::vector<int> arr;
for (int num:nums){res ^= num;}
//res &= -res;
// 防止溢出
res = (res == INT_MIN ? res : res & (-res));
for (int num:nums){
if ((num & res) == res) temp1 ^= num;
else temp2 ^= num;
}
arr.push_back(temp1);
arr.push_back(temp2);
return arr;
}
};
使用res &= -res;会报错
Line 8: Char 16: runtime error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself (solution.cpp)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:17:16 代码尝试对值-2147483648进行取反操作,而这是32位有符号整数的最小值。
对这个值进行取反操作会导致溢出情况,而在C或C++中,溢出是未定义行为。溢出发生在算术操作的结果超过数据类型能够表示的最大或最小值时。
\[-2^{31}<=\text{ nums [i]}<=2^{31}-1
\]

我们首先要区分一下整数取反(-res)和二进制按位取反(~res)。

具体参考:https://www.cnblogs.com/trmbh12/p/17775783.html

这里是整数取反,由于负数范围大于正数,所以会发生溢出。

但是为什么会是这个范围呢?负数为什么会多出一个呢?

具体请参考:https://www.cnblogs.com/trmbh12/p/17773283.html

这里使用 \(\text{res = (res = INT_MIN ? res : res & (-res));}\)

因为INT_MIN 对应的是1000.....,只有最高位为1,所以不需要res & (-res),直接等于原数即可,同时可以避免溢出问题>

260. 只出现一次的数字 III的更多相关文章

  1. Java实现 LeetCode 260 只出现一次的数字 III(三)

    260. 只出现一次的数字 III 给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次. 找出只出现一次的那两个元素. 示例 : 输入: [1,2,1,3,2,5] 输出 ...

  2. Leetcode 260.只出现一次的数字III

    只出现一次的数字III 给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次. 找出只出现一次的那两个元素. 示例 : 输入: [1,2,1,3,2,5] 输出: [3,5 ...

  3. LeetCode 260. 只出现一次的数字 III(Single Number III)

    题目描述 给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次. 找出只出现一次的那两个元素. 示例 : 输入: [1,2,1,3,2,5] 输出: [3,5] 注意: 结 ...

  4. LeetCode 260. Single Number III(只出现一次的数字 III)

    LeetCode 260. Single Number III(只出现一次的数字 III)

  5. [Swift]LeetCode260. 只出现一次的数字 III | Single Number III

    Given an array of numbers nums, in which exactly two elements appear only once and all the other ele ...

  6. Leetcode 137. 只出现一次的数字 II - 题解

    Leetcode 137. 只出现一次的数字 II - 题解 137. Single Number II 在线提交: https://leetcode.com/problems/single-numb ...

  7. leetcode 136. Single Number 、 137. Single Number II 、 260. Single Number III(剑指offer40 数组中只出现一次的数字)

    136. Single Number 除了一个数字,其他数字都出现了两遍. 用亦或解决,亦或的特点:1.相同的数结果为0,不同的数结果为1 2.与自己亦或为0,与0亦或为原来的数 class Solu ...

  8. 【剑指Offer】数组中只出现一次的数字 解题报告(Python)

    [剑指Offer]数组中只出现一次的数字 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-intervie ...

  9. 剑指Offer 数组中只出现一次的数字

    题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字.   思路: 因为有2个数字只出现了一次,而其他的数字都是2次,可以通过异或运算,得到最后这2个只 ...

  10. 59. 总结篇:数组中N(n=1,2,3)个只出现一次的数字[find N numbers which appear only once in array]

    [本文链接] http://www.cnblogs.com/hellogiser/p/find-n-numbers-which-appear-only-once-in-array.html [题目] ...

随机推荐

  1. 技本功|Hive优化之Spark执行引擎参数调优(二)

    Hive是大数据领域常用的组件之一,主要是大数据离线数仓的运算,关于Hive的性能调优在日常工作和面试中是经常涉及的的一个点,因此掌握一些Hive调优是必不可少的一项技能.影响Hive效率的主要有数据 ...

  2. Asp .Net Core 系列: 集成 CORS跨域配置

    目录 什么是CORS? Asp .Net Core 种如何配置CORS? CorsPolicyBuilder类详解 注册以及使用策略三种方式 EnableCors 和 DisableCors 特性 关 ...

  3. $router.push跳转页面传参

    $router.push传参与收参 //传参 <el-button type="text" @click="$router.push('/games/Match?i ...

  4. 为什么程序猿DD热衷于内容输出与分享?

    一.热衷于内容输出与分享 我是程序猿DD,大家知道我热衷于内容输出与分享.比如我一直有在产出博客或维护开源项目,是因为平时不沉迷游戏或追剧,空下来就喜欢整理整理最近碰到的问题,那么写写博客正好是一种比 ...

  5. ReactNative环境安装

    一.Homebrew 采用 Homebrew 镜像源及工具,切换到国内. /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/Homebre ...

  6. BugBuilder: 高质量大规模缺陷库自动构建方法

    摘要:本文提出并开发了高质量大规模缺陷库全自动构建方法BugBuilder,自动从版本控制系统中的人为编写的补丁中提取完整且精准的缺陷修复补丁. 本文分享自华为云社区<BugBuilder: 高 ...

  7. 聊聊LiteOS事件模块的结构体、初始化及常用操作

    摘要:本文通过分析LiteOS事件模块的源码,深入掌握事件的使用. 事件(Event)是一种任务间通信的机制,可用于任务间的同步.多任务环境下,任务之间往往需要同步操作,一个等待即是一个同步.事件可以 ...

  8. IoT技术的最后决战!百万大奖究竟花落谁家?

    2022年5月25日华为云IoT创新应用开发大赛决赛路演正式打响! 华为云IoT创新应用开发大赛是华为云面向IoT产业领域的重量级精品赛事,自去年11月上线以来,受到了物联网协会.生态伙伴.产业基地等 ...

  9. DevSecOps软件安全开发实践

    摘要:DevSecOps 的理念是将安全防护流程有机地融入传统的 DevOps 流程中,为研发安全提供强有力保证,安全工具支撑研发阶段安全要求落地. 本文分享自华为云社区<DevSecOps软件 ...

  10. 物联网企业该如何与华为云合作,这份FAQ值得一看

    摘要:关于华为云DevRun智联生活行业加速器,梳理出伙伴和企业最关心的问题,并逐一解答. 自华为云DevRun智联生活行业加速器发布以来,一直在为产业链上下游的企业提供技术.生态建设.商业变现等资源 ...