算法-尋找數組中的重複值
尋找數組中的重複值
題目來源於:Leetcode-287。本題歸類到簡單我無法理解…要滿足四個條件需要用很特定的解法,面試中要是用到的話很可能是在給自己挖坑,所以我這裏只講幾種能滿足一部分條件的解法。
給定一個包含 n + 1 個整數的數組 nums,其數字都在 1 到 n 之間(包括 1 和 n),可知至少存在一個重複的整數。假設只有一個重複的整數,找出這個重複的數。
示例 1:
輸入: [1,3,4,2,2]
輸出: 2
示例 2:
輸入: [3,1,3,4,2]
輸出: 3
說明:
1、不能更改原數組(假設數組是隻讀的)。
2、只能使用額外的 O(1) 的空間。
3、時間複雜度小於 O(n2) 。
4、數組中只有一個重複的數字,但它可能不止重複出現一次。
下面給出四種解法,
1、第一種基於排序,大家都懂的,滿足條件2、3、4。時間nlogn,空間n
2、第二種屬於元素歸位,其實和缺失最小正數那題挺像的,不過我們判斷的時候,應當以目標位置中的元素是不是與當前元素重複爲依據,如果索引不一致,但是值重複了,那就說明這是一個重複元素,滿足2、3、4並且比排序方式更快。時間n,空間1
3、第三種是利用哈希表,滿足1、3、4 。時間n空間n
4、第四種同樣是利用哈希表,不過該哈希表我們可以自建,滿足1、3、4。時間n空間n
第2類方式是比較好的。
//方式1,排序,時空複雜度爲nlog(n)和O(1)
public int findDuplicate(int[] nums) {
Arrays.sort(nums);
for(int i=1;i<nums.length;i++){
if(num[i]==nums[i-1]){
return nums[i];
}
}
return 0;
}
//方式2,按照最小缺失正數的思路來解,即元素歸位
//在數組中所有元素都處於1-n,我們把元素nums[i]放到i-1的位置
//時間複雜度O(N),空間複雜度O(1)
public int findDuplicate(int[] nums) {
for(int i=0;i<nums.length;i++){
while(i!=nums[i]-1){
if((i!=nums[i]-1)&&nums[nums[i]-1]==nums[i]){
return nums[i];
}
swap(nums,nums[i]-1,i);
}
}
return 0;
}
private void swap(int nums[],int i,int j){
int temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
//方式3,使用HashSet來映射,時空複雜度均爲O(N)
public int findDuplicate(int[] nums) {
Set<Integer> set=new HashSet<>();
for(int i=0;i<nums.length;i++){
if(set.contains(nums[i])){
return nums[i];
}
set.add(nums[i]);
}
return 0;
}
//方式4,自建map來映射,時空複雜度均爲O(N)
public int findDuplicate(int[] nums) {
int[] map=new int[nums.length];
for(int i=0;i<nums.length;i++){
if(map[nums[i]]==1){
return nums[i];
}
map[nums[i]]++;
}
return 0;
}