前言
在力扣网连续写了几道寻找数组中消失数字以及重复数字的题,发现有一些解法真是过于精妙,那就记录一波咯~~~~废话不多说开始吧!
剑指 Offer 03. 数组中重复的数字
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
力扣原题传送门
1、哈希表法
使用哈希表记录出现过的数字,一边遍历数组一边查询此数是否存在于哈希表中
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
unordered_set<int> historyNums;
for(auto& p:nums){
if(!historyNums.count(p))
historyNums.insert(p);
else return p;
}
return -1;
}
};
一次遍历,时间复杂度O(N),使用哈希额外空间,空间复杂度O(N);
2、标记法
巧妙之处在于 nums 里的所有数字都在 0~n-1 的范围内 ,刚好对应的是长度为n的数组下标,我们如果将数组中的元素当做下标使用,将这个数加上一个长度 n ,如果遍历过程发现一个数已经大于n - 1,说明该数之前被标记过,所以下标对应值就是我们需要寻找的重复数字。
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int len=nums.size();
for(auto& p:nums){
int index=p % len;
if(nums[index]>=len)
return index;
nums[index] += len;
}
return -1;
}
};
一次遍历,时间复杂度O(N),使用了常数空间,空间复杂度O(1);
448. 找到所有数组中消失的数字
给定一个范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次。
找到所有在 [1, n] 范围之间没有出现在数组中的数字。
扫描二维码关注公众号,回复:
12487221 查看本文章
您能在不使用额外空间且时间复杂度为O(n)的情况下完成这个任务吗? 你可以假定返回的数组不算在额外空间内。
原题传送
标记法
是不是似曾相识的感觉,没错,数组中的元素数值在 1~n 之间,与数组下标 0~n -1 相差为1,因此我们依然可以将这些元素减一的值当做下标使用进行标记,标记完我们再次遍历数组,若发现大于 0 的数,说明此数未被标记,那么它所对应的下标值加一的这个数肯定不在数组中(说得比较乱,可能代码比较好理解一些)
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
int n = nums.size();
for (int i = 0; i < n; i++) {
//遍历数组进行标记
int index = abs(nums[i]) - 1;//下标需要取绝对值,因为有些元素被标记成了负数
if (nums[index] > 0)//已经被标记过一次的数就不需要再次标记
nums[index] = 0 - nums[index];
}
vector<int> res;
for (int i = 0; i < n; i++)
if (nums[i] > 0)
res.push_back(i + 1);
return res;
}
};
先到这里,持续更新~~~