LeetCode:劍指Offer 03. 數組中重複的數字
文章目錄
原題LeetCode鏈接:劍指Offer 03. 數組中重複的數字
題目:找出數組中重複的數字
在一個長度爲 n 的數組 nums
裏的所有數字都在 0~n-1 的範圍內。數組中某些數字是重複的,但不知道有幾個數字重複了,也不知道每個數字重複了幾次。請找出數組中任意一個重複的數字。
示例1:
輸入:
[2, 3, 1, 0, 2, 5, 3]
輸出:2或3
限制:2 ≤ n ≤ 100000
方法一:排序
思路:數組元素是數字,對其進行排序,若有重複則在排序後數組的相鄰位置,遍歷數組即可找到。排序時間複雜度O(nlogn)
,空間複雜度O(1)
。C++代碼如下:
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
sort(nums.begin(), nums.end());
int length = nums.size();
for(int i = 0; i < length-1; i++){
if(nums[i] == nums[i+1]){
return nums[i];
}
}
return -1;
}
};
tips: sort()
用法:
頭文件:#include<algorithm>
void sort (RandomAccessIterator first, RandomAccessIterator last);
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
first
:待排序數組起始位置;
last
:待排序數組末尾位置,要排序的最後一個元素的後一個元素位置,[first,last);
comp
:排序的方法,可以是升序也可以是降序,不寫則默認升序。
方法二:集合法、unordered_set
思路:首先構建一個空集合,然後遍歷數組,如果元素不在集合中則將其插入集合中;若元素在集合中,則說明有重複。
tips :set
內部使用紅黑樹實現,具有自動排序的功能,因此內部元素在任何時候都是有序的;unordered_set
基於哈希表,數據插入和查找時間複雜度低,代價是消耗較多內存,不能自動排序。本題只需要插入與查找,因此選用unordered_set
時間上的差別可自行嘗試使用兩種結構進行提交。空間複雜度O(n)
,時間複雜度爲O(n)
。C++代碼如下:
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
unordered_set<int> s;
int length = nums.size();
for(int i = 0; i < length; i++){
if(s.find(nums[i]) == s.end()){
s.insert(nums[i]);
}
else{
return nums[i];
}
}
return -1;
}
};
方法三:就地交換
思路:因爲數組中的數字都是在0~n-1
範圍內的,如果沒有重複的元素那麼數據值和下標應該是相等的。而如果有重複的值的話,有些位置放的就不是對應的值,那麼我們可以嘗試將它放回對應的位置。
1)如果對應的位置有一個符合的元素,就說明該數字重複了;
2)如果對應的位置也不是符合的元素,那麼就將兩者交換,將上一個元素和正確位置配對,繼續尋找新的元素的位置。
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int length = nums.size();
for(int i = 0; i < length; i++){
if(i == nums[i]){//如果元素和位置對應,則繼續
continue;
}
else{//否則
while(i != nums[i]){//循環,直到元素與位置對應
if(nums[nums[i]] == nums[i]){//此元素對應的位置上已經有一個符合的了
return nums[i];//說明已經重複,返回元素即可
}
else{//元素對應位置上也是不符合的元素,那麼就和此元素交換使它符合,然後繼續尋找新位置
int temp = nums[nums[i]];
nums[nums[i]] = nums[i];
nums[i] = temp;
}
}
}
}
return -1;
}
};
如果有錯誤之處,還望指出!