题目来源
题目描述
题目解析
关键点在于两两相消
使用set
题目中让我们在线性的时间复杂度内求解,那么一个非常直接的思路就是使用 HashSet,利用其常数级的查找速度。遍历数组中的每个数字,若当前数字已经在 HashSet 中了,则将 HashSet 中的该数字移除,否则就加入 HashSet。这相当于两两抵消了,最终凡事出现两次的数字都被移除了 HashSet,唯一剩下的那个就是单独数字了
- cpp
int singleNumber(vector<int>& nums) {
std::unordered_set<int> set;
set.insert(nums[0]);
for (int i = 1; i < nums.size(); ++i) {
if(set.count(nums[i]) ){
set.erase(nums[i]);
}else{
set.insert(nums[i]);
}
}
return *set.begin();
}
使用异或相消
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ans = nums[0];
for (int i = 1; i < nums.size(); ++i) {
ans ^= nums[i];
}
return ans;
}
};
判断排序数组前后元素是否相等
class Solution {
public:
int singleNumber(vector<int>& nums) {
sort(nums.begin(), nums.end());
int size = nums.size();
if(size == 1){
return nums[0];
}
// 判断第一个
if(nums[0] != nums[1]){
return nums[0];
}
// 判断最后一个
if(nums[size - 1] != nums[size - 2]){
return nums[size - 1];
}
// 判断其他
for (int i = 1; i < size - 1; ++i) {
if(nums[i - 1] != nums[i] && nums[i] != nums[i + 1]){
return nums[i];
}
}
return -1;
}
};
求和
通过 HashSet 保存数组内的元素,然后进行求和(setsum),那么得到的这个和则为去除掉重复元素的和,我们也可以得到所有元素和(numsum)。因为我们其他元素都出现两次,仅有一个元素出现一次,那我们通过 setsum * 2 - numsum 得到的元素则为出现一次的数。
class Solution {
int singleNumber(std::vector<int> nums) {
if (nums.size() == 1){
return nums[0];
}
std::set<int> set;
int setsum = 0;
int numsum = 0;
for (int x : nums) {
//所有元素的和
numsum += x;
if (!set.count(x)) {
//HashSet内元素的和
setsum += x;
}
set.emplace(x);
}
//返回值
return setsum * 2 - numsum;
}
}
类似题目
题目 | 思路 |
---|---|
leetcode:41. 无序数组中缺失的第一个正整数(数组数据范围[-oo, +oo]) First Missing Positive | 应该去垃圾区的情况:当前数 <= L ,当前数 > 右边界 ,出现了重复 |
leetcode:268. 无序数组缺失的那个数(数组数据范围在[0, n],数据长度为n) Missing Number | 如果我们补充一个完整的数组和原数组进行组合,那所求解的问题就变成了 只出现一次的数字。 |
leetcode:448. 无序数组缺失的那个数(数组数据范围在[1, n],数据长度为n) Find All Numbers Disappeared in an Array | 标记法:在原数组上进行一次遍历,在遍历的过程中,将遇到的元素所对应的index下的元素标记为负。最终哪些index下的元素没有被标记的则说明,这个index对应额元素没有出现过。置换法: |
leetcode:136. 无序数组出现一次的数字(出现一次的数字有一个,其他出现两次)Single Number | 异或相消,剩下来的就是想要的 |
leetcode:137. 无序数组出现一次的数字(出现一次的数字有一个,其他出现三次) II Single Number IISingle Number II | 对于出现三次的数字,各个二进制位出现的次数都是3的倍数。因此,统计所有数字的各二进制位中1的出现次数,并对3求余,结果则为只出现一次的数字(通用解法)。实现:对int的32个位每个位进行依次判断该位1的个数求余3后是否为1,如果为1说明结果该位二进制为1可以将结果加上去。最终得到的值即为答案。 |
leetcode:260. 无序数组出现一次的数字(出现一次的数字有两个,其余出现两次)Single Number III | 先将元素分成两组,然后每组包含一个目标值,那么异或之后,每组得到一个目标值。比如a,b,a,b,c,d,e,f,e,f,分组后;A组:a, a , b, b, c 异或得到 c;B组:e, e, f, f, d 异或得到 d |
leetcode:287.无序数组出现多次的数字(一个数出现多次,其他数出现一次或者零次) (数组数据范围在[1, n],数据长度为n+1) Find the Duplicate Number | 因为不允许修改原数组,所以不能用标记法。而一般对于链表,数组中要求找重复的数字或者节点,都可以考虑用快慢指针的方法来解,也就是入环节点就是那个重复的数 |
leetcode:442.无序数组出现两次的整数(每个数出现一次或者两次,数组数据范围在[1, n])) Find All Duplicates in an Array | 标记法:对于每个nums[i],我们将其对应的nums[nums[i] - 1]取相反数,如果其已经是负数了,说明之前存在过,我们将其加入结果res中即可;置换法: 将nums[i]置换到其对应的位置nums[nums[i]-1]上去,最后在对应位置检验,如果nums[i]和i+1不等,那么我们将nums[i]存入结果res中即可 |
leetcode:645. 无序数组,有一个数字重复出现了一次,从而造成了另一个数字的缺失,请找出重复的数字和缺失的数字(数据范围在[1, n],数据长度为n) Set Mismatch | 假设每个人各司其职, 那么每个岗位上就是相应的人员,并且各司其职, 但是现在混入了一个;闲杂人等, 他又害怕被人发现, 于是他就别人的岗位上站着, 结果等着等着, 这个岗位上应该来的人来了;他一看, 自己掩饰不过去了(毕竟人家不会跑到别的岗位上,抢别人的活干, 于是他就这么一直碰运气。 一直走到那个没来上岗的那个人的岗位上去, 这样谁都不会发现他是的闲杂人等.而且每个岗位上都满员了. |
leetcode:142. 环形链表 II | |
leetcode:540. 有序数组中的单一元素(其他出现两次) | 二分 |
leetcode:389. 字符t比字符s多出的那个数 Find the Difference | 异或 |
765. 情侣牵手Couples Holding Hands | |
565. 数组嵌套 Array Nesting | |
1207. 独一无二的出现次数 | 先统计数字出现的频率,然后看相同频率是否重复出现 |