在leetcode上看到這道題,許多同道給出了驚艷和炫酷的解答方法。
題目:給定一個數組nums,數組中元素均為整數,返回不在nums中的最小正整數
:type: nums -> list[int]
:rtype: i -> integer
:example: nums = [2,4,7,1,-3,0,5],返回3; nums = [3,2,4,5,6] 返回 1
線性時間復雜度的常規實現不難:返回值一定在閉區間[1,k+1]中,創建一個長度為k+1的數組,並全部初始化為0,然后讀取原數組,將[1,k]區間內的值寫入新數組。最后再返回新數組中第一個0元素的位置 加 1.
算法一(空間復雜度O(N)):
1 def findmissing(nums): 2 r = [0] * (len(nums) + 1) 3 for num in nums: 4 if 0 < num <= len(nums): 5 r[num - 1] = 1 6 7 for i in range(len(r)): 8 if r[i] == 0: 9 return i + 1 10
不難看出,空間復雜度為r數組的長度,即O(n).如果在時間復雜度不變的情況下降低空間復雜度,我們需要在原數組中記錄信息。
(1)清除無效數據,將小於等於0 和 大於數組長度的值清除;
(2)記錄 [1,len(nums)]區間內的值,將目標位置與所在位置的值交換。
算法二(空間復雜度O(1)):
def findmissing(nums): i = 0 while i < len(nums): if 0 < nums[i] <= len(nums) and nums[nums[i]-1] != nums[i]: nums[nums[i]-1],nums[i] = nums[i], nums[nums[i]-1] else: i += 1 for i in range(len(nums)): if nums[i] != i + 1: return i + 1 return len(nums) + 1
除了采用交換位置的方法記錄[1,len(nums)]的值,還可以利用索引來做hash表。
算法三(空間復雜度O(1)):
1 def findmissing(nums): 2 # 將無效數據置為0 3 for i in range(len(nums)): 4 if nums[i] <=0 or nums[i] > len(nums): 5 nums[i] = 0 6 7 nums.append(0) 8 n = len(nums) 9 10 for i in range(len(nums)): 11 nums[nums[i] % n] += n 12 13 for i in range(1,len(nums)): 14 if nums[i] / n == 0: 15 return i 16 return n