存在重複元素(I II III)小結

217. 存在重複元素

給定一個整數數組,判斷是否存在重複元素。

如果任何值在數組中出現至少兩次,函數返回 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方法性能會更好。

 

219. 存在重複元素 II

給定一個整數數組和一個整數 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;
    }
}

 

220. 存在重複元素 III

給定一個整數數組,判斷數組中是否有兩個不同的索引 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;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章