问题
力扣的题:
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是
重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意
一个重复的数字
我的解法
我先排序,然后找相邻的元素有没有一样的。
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
sort(nums.begin(), nums.end());
for(vector<int>::iterator it=nums.begin(); it!=nums.end()-1; it++){
if(*it == *(it+1)) return *it;
}
return -1;
}
};
示例代码
class Solution {
public:
Solution(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
int findRepeatNumber(vector<int>& nums) {
int i = 0, n = nums.size();
while(i < n){
if(nums[i] == i){
i++;
continue;
}
if(nums[nums[i]] == nums[i]) return nums[i];
swap(nums[i], nums[nums[i]]);
}
return -1;
}
};
它的做法其实也有排序,看着比较难懂。它是看开第i个位置是不是放了第i个元素,如果不是,就把它放到它对应的位置去。排序过程中发现重复了,就return。
评论区网友的解释
这道题的评论区有个 @普通人能想到的解法 ,它用python给出了3种解法的差异。下面是它的原话:
- Python3 方法一:先排序,然后看相邻元素是否有相同的,有直接return。 不过很慢,时间O(nlogn)了,空间O(1)
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
nums.sort()
pre = nums[0]
n = len(nums)
for index in range(1, n):
if pre == nums[index]:
return pre
pre = nums[index]
- 方法二:哈希表 时间O(n),空间O(n)
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
repeatDict = {}
for num in nums:
if num not in repeatDict:
repeatDict[num] = 1
else:
return num
- 方法三:时间复杂度O(n),空间复杂度O(1)。可以看做是一种原地哈希,不过没有用到字典。具体做法就是因为题目中给的元素是 < len(nums)的,所以我们可以让 位置i 的地方放元素i。如果位置i的元素不是i的话,那么我们就把i元素的位置放到它应该在的位置,即 nums[i] 和nums[nums[i]]的元素交换,这样就把原来在nums[i]的元素正确归位了。如果发现 要把 nums[i]正确归位的时候,发现nums[i](这个nums[i]是下标)那个位置上的元素和要归位的元素已经一样了,说明就重复了,重复了就return
class Solution:
def findRepeatNumber(self, nums) -> int:
n = len(nums)
for i in range(n):
while i != nums[i]:
if nums[i] == nums[nums[i]]:
return nums[i]
temp = nums[i]
nums[i], nums[temp] = nums[temp], nums[i]
# 注意这里不要写成nums[i], nums[nums[i]] = nums[nums[i]], nums[i]
# 这种嵌套的直接交换在python里面得到的不是你想要的。提交了好几次发现之间在里面死循环了,debug了一下才发现有问题