(python)劍指Offer:數組中重復的數字


問題描述

  在長度為n的數組中,所有的元素都是0到n-1的范圍內。 數組中的某些數字是重復的,但不知道有幾個重復的數字,也不知道重復了幾次,請找出任意重復的數字。 例如,輸入長度為7的數組{2,3,1,0,2,5,3},那么對應的輸出為2或3。

 

解題思路

1、判斷輸入數組有無元素非法 
2、從頭掃到尾,只要當前元素值與下標不同,就做一次判斷,numbers[i]與numbers[numbers[i]],相等就認為找到了重復元素,返回true,否則就交換兩者,繼續循環。直到最后還沒找到認為沒找到重復元素,返回false

時間復雜度:O(n),空間復雜度:O(1)

 

解題代碼(python實現)

#在長度為n的數組中,所有的元素都是0到n-1的范圍內。 數組中的某些數字是重復的,但不知道有幾個重復的數字,
#也不知道重復了幾次,請找出任意重復的數字。 例如,輸入長度為7的數組{2,3,1,0,2,5,3},那么對應的輸出為2或3
def repeat_num(li):
    for index, value in enumerate(li):
        if index != value:
            li[index], li[value] = li[value], li[index]
        if index != value and value == li[value]:
            return li[index]

li = [0, 1, 2, 3, 3, 4, 6, 4]
print(repeat_num(li))

 

擴展:

題目描述:
  在一個長度為n+1的數組里的所有數字都在1~n的范圍內,所以數組中至少有一個數字是重復的。請找出數組中任意一個重復的數字,但是不能修改輸入的數組。

思路:

采用二分法查找,時間復雜度為 O(nlogn)

在數字 1~n 中取中間值 m = (1+n) / 2, 此時數字包括 1~m, m+1~n 兩段;
遍歷數組,獲得數字 1~m 的個數;
如果數字 1~m 的個數大於 m,說明 1~m 這一段內肯定有重復數字,那么在這一段內繼續取中間值比較;
如果數字 1~m 的個數等於 m,這一段不一定有重復數字,比較后一段;
如果數字 1~m 的個數小於 m,說明 m+1~n 這一段一定有重復數字,在后一段取中間值比較;
按照上述方法一直取中間值比較,直到只剩一個數字且這個數字出現次數超過 1 ,該數字即為重復數字

class solution():
    def duplicate(self,numbers):
        if numbers == []:
            return False
        length = len(numbers)
        start = 1
        end = length - 1
        while end >= start:
            middle = (end - start)//2 + start
            count = self.countNum(numbers, length, start, middle)
            if end == start:
                if count > 1:
                    return True
                else:
                    break
            if count > middle - start + 1:
                end = middle
            else:
                start = middle + 1
        return False

    def countNum(self, numbers, length, start, end):
        count = 0
        for i in range(length):
            if numbers[i] < 1 or numbers[i] > length:
                return False
            if start <= numbers[i] <= end:
                count += 1
        return count

ss = solution()
print(ss.duplicate([4,2,3,1,2,5]))
print(ss.duplicate([4,2,3,1]))

  這種方法雖然不需要輔助空間O(n),但是后面每半個區間都需要遍歷整個數組,函數countNum將被調用O(logn)次,每次需要O(n)的時間,因此總的時間復雜度是O(nlogn),空間復雜度為O(l)。相當於用時間換空間了。
  現在來總結下關於數組中重復數字的問題,利用輔助空間的話,時間和空間復雜度都是O(n);利用下標於數字對應關系的話時間復雜度是O(n),空間復雜度是O(l),但是需要改變數組;利用二分查找類似思路的方法,時間復雜度是O(nlogn),空間復雜度O(l),所以要問清楚面試官他想要空間效率高的呢?還是時間效率高的呢?能不能改變數組呢?一方面體現交流能力,一方面能最快的寫出答案。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM