03、找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。示例 1:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
思路一:哈希,映射set.时间O(n),空间O(n)
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
set<int> st;
for(auto &i:nums){
if(st.count(i)) return i;
else st.insert(i);
}
return 0;
}
};
执行用时:188 ms, 在所有 C++ 提交中击败了6.91%的用户
内存消耗:28 MB, 在所有 C++ 提交中击败了9.22%的用户
改:无排序的set。空间换时间。
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
unordered_set<int> st;
for(auto &i:nums){
if(st.count(i)) return i;
else st.insert(i);
}
return 0;
}
};
执行用时:120 ms, 在所有 C++ 提交中击败了43.76%的用户
内存消耗:27.2 MB, 在所有 C++ 提交中击败了31.40%的用户
思路二:哈希,vector来mark元素。时间O(n),空间O(n)。空间换时间。
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
vector<int> mark(nums.size(), 0);
for(auto &i:nums){
if(mark[i]) return i;
else mark[i] = 1;
}
return -1;
}
};
执行用时:76 ms, 在所有 C++ 提交中击败了94.99%的用户
内存消耗:23.4 MB, 在所有 C++ 提交中击败了38.53%的用户
思路三:排序。时间O(logn+n),空间O(1)。时间换空间。
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
sort(nums.begin(),nums.end());
for(int i = 0; i < nums.size()-1; i++){
if(nums[i] == nums[i+1]) return nums[i];
}
return -1;
}
};
执行用时:140 ms, 在所有 C++ 提交中击败了28.94%的用户
内存消耗:22.7 MB, 在所有 C++ 提交中击败了56.68%的用户
.
思路四:原地哈希。鸽巢原理。
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
for(int i = 0; i < nums.size();i++){
while(nums[i]!=i){
if(nums[i] == nums[nums[i]]) return nums[i];
int tmp = nums[nums[i]];
nums[nums[i]] = nums[i];
nums[i] = tmp;
}
}
return -1;
}
};
执行用时:76 ms, 在所有 C++ 提交中击败了94.99%的用户
内存消耗:22.7 MB, 在所有 C++ 提交中击败了58.01%的用户