給定一個整數數組,判斷是否存在重複元素。
如果任何值在數組中出現至少兩次,函數返回 true。如果數組中每個元素都不相同,則返回 false。
示例 1:
輸入: [1,2,3,1]
輸出: true
示例 2:
輸入: [1,2,3,4]
輸出: false
示例 3:
輸入: [1,1,1,3,3,4,3,2,4,2]
輸出: true
解法1:
用HashSet解決。
class Solution {
public boolean containsDuplicate(int[] nums) {
Set<Integer> set =new HashSet();
int i=0;
while(i<nums.length){
if(set.contains(nums[i]))
return true;
if(!set.contains(nums[i]))
set.add(nums[i]);
i++;
}
return false;
}
}
時間複雜度 : O(n)。
search() 和 insert() 各自使用 n 次,每個操作耗費常數時間。
空間複雜度 : O(n)。哈希表佔用的空間與元素數量是線性關係。
解法2:
先排序再查找,排完序後,相同的元素一定相鄰。
class Solution {
public boolean containsDuplicate(int[] nums) {
if(nums==null||nums.length<2)
return false;
Arrays.sort(nums);
int pre=nums[0],i=1;
while(i<nums.length){
if(pre==nums[i])
return true;
pre=nums[i];
i++;
}
return false;
}
}
時間複雜度 : O(nlogn)。
排序的複雜度是 O(nlogn),掃描的複雜度是 O(n)。整個算法主要由排序過程決定,因此是 O(nlogn)。
空間複雜度 : O(1)。
這取決於具體的排序算法實現,通常而言,使用 堆排序 的話,是 O(1)。
一般而言,編程語言自帶的sort方法性能會更好。
給定一個整數數組和一個整數 k,判斷數組中是否存在兩個不同的索引 i 和 j,使得 nums [i] = nums [j],並且 i 和 j 的差的絕對值最大爲 k。
示例 1:
輸入: nums = [1,2,3,1], k = 3
輸出: true
示例 2:
輸入: nums = [1,0,1,1], k = 1
輸出: true
示例 3:
輸入: nums = [1,2,3,1,2,3], k = 2
輸出: false
解法:
滑動窗口的思路,維持一個滑動窗口大小爲K,然後對於這K個值來說,又轉化爲了第一個問題,從而選擇合適的解法.
class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
if(nums==null||nums.length<2)
return false;
Set<Integer> set = new HashSet();
int i=0;
while(i<nums.length){
if(set.contains(nums[i]))
return true;
set.add(nums[i]);
if(set.size()>k)
set.remove(nums[i-k]);
i++;
}
return false;
}
}
給定一個整數數組,判斷數組中是否有兩個不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的絕對值最大爲 t,並且 i 和 j 之間的差的絕對值最大爲 ķ。
示例 1:
輸入: nums = [1,2,3,1], k = 3, t = 0
輸出: true
示例 2:
輸入: nums = [1,0,1,1], k = 1, t = 2
輸出: true
示例 3:
輸入: nums = [1,5,9,1,5,9], k = 2, t = 3
輸出: false
解法:
仍然是滑動窗口 大小爲K 的思路。
處理絕對值 t 時,只需 使得 >= 當前元素current 得最小值 small滿足 current>=small-t
以及 使得 <=當前元素current 的最大值 large滿足 current<=large+t 即可。
用數軸來表示如下:
對於TreeSet
floor(E e) 方法返回在這個集合中 <= 給定元素的最大元素,如果不存在這樣的元素,返回null.
ceiling(E e) 方法返回在這個集合中 >= 給定元素的最小元素,如果不存在這樣的元素,返回null.
class Solution {
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
TreeSet<Integer> set=new TreeSet<>();
for(int i=0;i<nums.length;i++){
Integer cel=set.ceiling(nums[i]);
if(cel!=null&&nums[i]>=cel-t)
return true;
Integer gro=set.floor(nums[i]);
if(gro!=null&&nums[i]<=gro+t)
return true;
set.add(nums[i]);
if(set.size()>k)
set.remove(nums[i-k]);
}
return false;
}
}