【劍指offer】劍指offer——數組中重複的數字

數組中重複的數字

算是一道簡單題,但是需要大家考慮時間和空間的複雜度,以及是否能修改原數組等情況。框裏圈出來的是解題的關鍵喲。
在這裏插入圖片描述

法一:暴力

很容易想,也很暴力!
雙層循環嵌套找到相同的數,時間複雜度達到O(n),空間複雜度O(1)

public int findRepeatNumber(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int n = nums.length;
        for (int i= 0; i < n; i++) {
            for (int j = i+1; j < n; j ++) {
                if (nums[i] == nums[j]) {
                    return nums[i];
                }
            }
        }
        return -1;
    }

法二 :額外定義數組

很容易想到用空間換時間的方法,於是定義一個數組。由於題目明確了元素的大小不會超過數組的長度,所以定義數組長度設爲num.length。
遍歷數組,比如num[5]的元素是3,那麼新數組下標爲3處就加一,表示3已經出現過一次。
這樣時間複雜度是O(n)空間複雜度是O(n)

public int findRepeatNumber(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int[] count = new int[nums.length];

        for (int i= 0; i < nums.length ; i++) {
            if (count[nums[i]] != 0) {
                return nums[i];
            }
            count[nums[i]] ++;
        }
        return -1;
        
    }

法三:不開闢額外數組

核心思想與法二相同,只是這次沒有重新開闢新的空間,而是對原來的數組進行了修改。
正常情況下排序後,下標爲i處的元素就是i 。
所以,遍歷一遍數組,如果i處的元素不是i 那我們就把它交換到nums[i]處,一次不一定可以使得nums[i] = i ,那就使用while循環,直到滿足i處元素就是i。
例如:
對於i=0,第一次nums[0] = 2,就和nums[2]處元素1交換交換
交換後,nums[0] = 1就和nums[1]處元素3交換
交換後,nums[0] = 3就和nums[3]處元素0交換
至此,nums[0]就等於0
如此循環。
在這裏插入圖片描述
如果下次交換時碰到要交換過去的位置上的元素剛好等於自己,那就找到了。由於沒有開闢新數組,時間複雜度O(n)空間複雜度O(1)
雖然for循環又嵌套了while循環,但是每一個數來到它應該在的位置以後,位置就不會再變化。

 public int findRepeatNumber(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int n = nums.length;
        for (int i = 0; i < n; i ++) {
            while (nums[i] != i) {
                if (nums[i] == nums[nums[i]]) {
                    return nums[i];
                }
                int tmp = nums[i];
                nums[i] = nums[tmp];
                nums[tmp] = tmp;
                
            }
        }
        return -1;
        
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章