【LeetCode.26】 刪除排序數組中的重複項

題目描述

給定一個排序數組,你需要在 原地 刪除重複出現的元素,使得每個元素只出現一次,返回移除後數組的新長度。

不要使用額外的數組空間,你必須在 原地 修改輸入數組 並在使用 O(1) 額外空間的條件下完成。

示例 1:

給定數組 nums = [1,1,2],
函數應該返回新的長度 2, 並且原數組 nums 的前兩個元素被修改爲 1, 2。
你不需要考慮數組中超出新長度後面的元素。

示例 2:

給定 nums = [0,0,1,1,1,2,2,3,3,4],
函數應該返回新的長度 5, 並且原數組 nums 的前五個元素被修改爲 0, 1, 2, 3, 4。你不需要考慮數組中超出新長度後面的元素。

理解題意

  • 原地修改數組,指的是直接對數組參數 取下標來修改數組元素,而不是通過將數組參數引用指向一個新的數組。
  • 數組肯定是排序好的。
  • 返回值爲不重複元素個數。

思路

在這裏插入圖片描述

  • 因爲整個過程好像是在往左壓實這個數組,所以我用了compact這個單詞。圖中我用藍色標識當前的壓實數組。
  • 當新的壓實元素加入壓實數組時,是通過賦值來實現的。而賦值是會覆蓋掉某個數組元素的,有兩種情況:被覆蓋的元素,本就是可以覆蓋的,比如它是重複元素;或者,原地賦值,這樣該索引上的元素不變。
  • cursor代表遍歷數組的索引,它從第二個元素開始,因爲只有一個元素的數組肯定無重複呀。
  • 在遍歷過程中,cursor所在元素需要和compareNum進行比較,因爲compareNum是當前已壓實數組的最後一個元素,如果和它不一樣,那說明cursor所在元素加入到壓實數組中去:具體操作就是,把cursor所在元素賦值給壓實數組之後的那個元素。
  • 壓實數組之後的那個元素的索引,即爲compactIndex。

具體流程是:

  • 遍歷數組,如果cursor所在元素與compareNum相同,那麼只增加cursor。
  • 如果cursor所在元素與compareNum不同,那麼除了增加cursor外,還需要壓實操作:把cursor所在元素賦值給 compactIndex下標元素,更新compareNum爲 cursor所在元素(因爲現在它纔是壓實數組最後一個元素),當然compactIndex也得加1.
  • 當然cursor到底末尾,結束循環。
  • 當數組裏沒有重複元素時,你會發現有原地賦值的情況(即每次檢測到新的壓實元素時,cursor和compactIndex總是一樣的),且每個新的壓實元素,都是執行了原地賦值了的。

優化:
這是我最開始想的算法,其實聰明的你已經發現:compareNum和compactIndex總是相鄰的,所以只需要保留一個就可以了。更進一步,compareNum你也不用用變量保存了,直接取下標就好了。

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        if len(nums) < 2:
            return len(nums)
        
        compactIndex = 1  #剛好是壓實數組的長度
        compareNum = nums[0]
        cursor = 1
        while( cursor < len(nums) ):
            if nums[cursor] != compareNum:
                nums[compactIndex] = compareNum = nums[cursor]
                compactIndex += 1
            cursor +=1
        return compactIndex

解法關鍵詞

  • 雙指針
  • 快慢指針

最快代碼

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        index = 0
        for i in range(1,len(nums)):
            if nums[i]  != nums[index]:  #每次和壓實數組最後元素比較
                index +=1  #如果不同,index+1,因爲新壓實元素需要放在後面
                nums[index] = nums[i]  #賦值新壓實元素
        return index+1 if nums else 0
  • index爲壓實數組的最後一個元素的索引。
  • 返回值爲index+1,因爲長度爲最大索引+1.
  • 沒有保存compareNum了,但是有compareNum的索引index,每次取下標來用的。
  • compactIndex也不用存了,因爲它永遠是index加1。
  • 還有最後這個return index+1 if nums else 0,差點給我看蒙了。其實就是if else的倒裝句和三目表達式的結合(nums ? index+1 : 0)。相當於下面:
if nums:
    index+1
else:
    0
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章