劍指offer第3:陣列中重複的數字
阿新 • • 發佈:2018-11-05
題目描述
在一個長度為n的數組裡的所有數字都在0到n-1的範圍內。 陣列中某些數字是重複的,但不知道有幾個數字是重複的。也不知道每個數字重複幾次。請找出陣列中任意一個重複的數字。 例如,如果輸入長度為7的陣列{2,3,1,0,2,5,3},那麼對應的輸出是第一個重複的數字2。
# -*- coding:utf-8 -*- class Solution: # 這裡要特別注意~找到任意重複的一個值並賦值到duplication[0] # 函式返回True/False def duplicate(self, numbers, duplication): # write code here if len(numbers)<=1: return False i=0 while i<=len(numbers): m=numbers[i] if m==i: i+=1 else: if numbers[i]==numbers[m]: return True else : temp=numbers[i] numbers[i]=numbers[m] numbers[m]=temp i+=1 return False
題目2:題目描述:
在一個長度為n+1的數組裡的所有數字都在1~n的範圍內,所以陣列中至少有一個數字是重複的。請找出陣列中任意一個重複的數字,但是不能修改輸入的陣列。
def find_dux_num(seq): if len(seq) <= 1 or seq is None: return None start, end = 1, len(seq) - 1 # 獲取數字1,n while start <= end: mid = (start+end) // 2 # 獲取中間數字 count = count_num(seq, start, mid) # 計算[start, mid]數字之間的數目 # 當只取到一個數字時,如果該數字出現數目大於1,就是重複數字 if start == end: if count > 1: return start else: break # 如果count數目 > 中間數字到起始數字之差,一定存在重複數字,繼續在這一段中求中間數比較 if count > mid - start + 1: end = mid # 否則在後一段中求中間數比較 else: start = mid + 1 return None def count_num(seq, start, end): count = 0 for i in seq: if start <= i <= end: count += 1 return count if __name__ == '__main__': print(find_dux_num([1, 2, 3, 4, 3])) 作者:大白杏仁 連結:https://www.jianshu.com/p/b35c528e01d7 來源:簡書 簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。
https://www.jianshu.com/p/b35c528e01d7 有詳細的介紹
這種方法雖然不需要輔助空間O(n),但是後面每半個區間都需要遍歷整個陣列,函式countNum將被呼叫O(logn)次,每次需要O(n)的時間,因此總的時間複雜度是O(nlogn),空間複雜度為O(l)。相當於用時間換空間了。
現在來總結下關於陣列中重複數字的問題,利用輔助空間的話,時間和空間複雜度都是O(n);利用下標於數字對應關係的話時間複雜度是O(n),空間複雜度是O(l),但是需要改變陣列;利用二分查詢類似思路的方法,時間複雜度是O(nlogn),空間複雜度O(l),所以要問清楚面試官他想要空間效率高的呢?還是時間效率高的呢?能不能改變陣列呢?一方面體現交流能力,一方面能最快的寫出答案。
還剩一個輔助空間法。