跳到主要內容

LeetCode 80,不使用外部空間的情況下對有序數組去重

本文始發於個人公眾號:TechFlow,原創不易,求個關注





今天是LeetCode專題的第49篇文章,我們一起來看LeetCode的第80題,有序數組去重II(Remove Duplicates from Sorted Array II)。


這題的官方難度是Medium,通過率是43.3%,點贊1104,反對690。這題的通過率有一點點高,然後點贊比也不是很高。說明這題偏容易,並且大家的評價偏低。也的確如此,我個人覺得,大家評價不好的主要原因還是這題偏容易了一些。


題面


其實從題目的標題當中我們已經可以得到很多信息了,實際上也的確如此,這題的題面和標題八九不離十,需要我們對一個有序的數組進行去重。不過去重的條件是最多允許一個元素出現兩次,也就是要將多餘的元素去掉。並且題目還限制了需要我們在原數組進行操作,對於空間複雜度的要求是。由於我們去除了元素之後會帶來數組長度的變化,所以我們最後需要返回完成之後數組的長度。


這是一種常規的做法,在C++以及一些古老的語言當中數組是不能變更長度的。我們想要在原數組上刪除數據,只能將要刪除的數據移動到數組末尾,然後返回變更之後的數組長度。這樣下游就通過返回的數組長度得知變更之後的數量變化。由於新晉的一些語言,比如Java、Python都支持數組長度變動,所以很少在這些語言的代碼當中看到這樣的用法了。


樣例


Given nums = [0,0,1,1,1,1,2,3,3],

Your function should return length = 7, with the first seven elements of nums being modified to 0, 0, 1, 1, 2, 3 and 3 respectively.

It doesn't matter what values are set beyond the returned length.

在這個樣例當中,由於1出現了4次,所以我們需要刪除掉2個1,那麼刪除之後的數組長度也會減少2,所以我們需要返回7,表示刪除之後的新的數組的有效長度是7。並且保證原數組當中前5個元素是[0, 0, 1, 1, 2, 3]


題解


刪除重複的元素本身並不複雜,唯一麻煩的是我們怎麼在不引入額外存儲的情況下完成這一點。如果你能抓住數組是有序的這一點,應該很容易想通:既然數組是有序的,那麼相同的元素必然排在一起。


既然相同的元素排在一起,那麼我們可以利用一個變量存儲當前元素出現的次數。如果遇到不同的元素,則將次數置為1。這樣我們就可以判斷出究竟哪些元素需要刪除,哪些元素需要保留了。


但是這就又引入了另外一個問題,我們怎麼來刪除這些重複的元素呢?因為我們不能引入額外的數組,需要在當前數組上完成。我們可以先假設沒有這個限制,我們會怎麼做?


new_nums = []
cur = None
for i in range(n):
if cur == nums[i]:
count += 1
else:
count = 1
cur = nums[i]
if count > 2:
continue
new_nums.append(nums[i])

由於有這個限制,所以我們要做的就是把new_nums這個數組去掉,其實去掉是很簡單的,因為我們可以讓nums這個數組自己覆蓋自己。因為產出的數據的數量一定是小於等於數組長度的,所以不會出現數組越界的問題。我們只需要維護一個下標記錄nums數組當中允許覆蓋的位置即可。


這個也是非常常見的做法,我們在之前的題目當中也曾經見到過。


class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
# start是起始覆蓋指針,指向第一個可以覆蓋的位置
start, cur, cnt = 0, None, 0
n = len(nums)
if n == 0:
return 0
for i in range(n):
if cur == nums[i]:
cnt += 1
else:
cnt = 1
cur = nums[i]
# 如果數量超過2,說明當前元素應該捨棄,則continue
if cnt > 2:
continue
# 否則用當前元素覆蓋start位置,並且start移動一位
else:
nums[start] = nums[i]
start += 1
return start

關於這段代碼,還有一個簡化版本,我們可以把cnt變量也省略掉。因為元素是有序的,我們可以直接用nums[i]和nums[i-2]進行判斷,如果相等,那麼說明重複的元素一定超過了兩個,當前元素需要跳過。


簡化之後的代碼如下:


class Solution(object):
def removeDuplicates(self, nums):
""" :type nums: List[int] :rtype: int """
i = 0
for n in nums:
if i < 2 or n != nums[i - 2]:
nums[i] = n
i += 1
return i

總結


今天的題目不難,總體來說算是Medium偏低難度,主要有兩點值得稱道。第一點是C++風格inplace變更數組的做法,第二點就是數組自我覆蓋的方法。除此之外,題目幾乎沒什麼難度,我想大家應該都能想出解法來。


如果喜歡本文,可以的話,請點個關注,給我一點鼓勵,也方便獲取更多文章。


本文使用 mdnice 排版



本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能



台北網頁設計公司這麼多該如何選擇?



※智慧手機時代的來臨,RWD網頁設計為架站首選



※評比南投搬家公司費用收費行情懶人包大公開



※幫你省時又省力,新北清潔一流服務好口碑



※回頭車貨運收費標準



Orignal From: LeetCode 80,不使用外部空間的情況下對有序數組去重

留言

這個網誌中的熱門文章

架構設計 | 異步處理流程,多種實現模式詳解

本文源碼:GitHub·點這裏 || GitEE·點這裏 一、異步處理 1、異步概念 異步處理不用阻塞當前線程來等待處理完成,而是允許後續操作,直至其它線程將處理完成,並回調通知此線程。 必須強調一個基礎邏輯,異步是一種設計理念,異步操作不等於多線程,MQ中間件,或者消息廣播,這些是可以實現異步處理的方式。 同步處理和異步處理相對,需要實時處理並響應,一旦超過時間會結束會話,在該過程中調用方一直在等待響應方處理完成並返回。同步類似電話溝通,需要實時對話,異步則類似短信交流,發送消息之後無需保持等待狀態。 2、異步處理優點 雖然異步處理不能實時響應,但是處理複雜業務場景,多數情況都會使用異步處理。 異步可以解耦業務間的流程關聯,降低耦合度; 降低接口響應時間,例如用戶註冊,異步生成相關信息表; 異步可以提高系統性能,提升吞吐量; 流量削峰即把請求先承接下來,然後在異步處理; 異步用在不同服務間,可以隔離服務,避免雪崩; 異步處理的實現方式有很多種,常見多線程,消息中間件,發布訂閱的廣播模式,其根據邏輯在於先把請求承接下來,放入容器中,在從容器中把請求取出,統一調度處理。 注意 :一定要監控任務是否產生積壓過度情況,任務如果積壓到雪崩之勢的地步,你會感覺每一片雪花都想勇闖天涯。 3、異步處理模式 異步流程處理的實現有好多方式,但是實際開發中常用的就那麼幾種,例如: 基於接口異步響應,常用在第三方對接流程; 基於消息生產和消費模式,解耦複雜流程; 基於發布和訂閱的廣播模式,常見系統通知 異步適用的業務場景,對數據強一致性的要求不高,異步處理的數據更多時候追求的是最終一致性。 二、接口響應異步 1、流程描述 基於接口異步響應的方式,有一個本地業務服務,第三方接口服務,流程如下: 本地服務發起請求,調用第三方服務接口; 請求包含業務參數,和成功或失敗的回調地址; 第三方服務實時響應流水號,作為該調用的標識; 之後第三方服務處理請求,得到最終處理結果; 如果處理成功,回調本地服務的成功通知接口; 如果處理失敗,回調本地服務的失敗通知接口; 整個流程基於部分異步和部分實時的模式,完整處理; 注意 :如...

.NET Core前後端分離快速開發框架(Core.3.0+AntdVue)

.NET Core前後端分離快速開發框架(Core.3.0+AntdVue) 目錄 引言 時間真快,轉眼今年又要過去了。回想今年,依次開源發布了 Colder.Fx.Net.AdminLTE(254Star) 、 Colder.Fx.Core.AdminLTE(335Star) 、 DotNettySocket(82Star) 、 IdHelper(47Star) ,這些框架及組件都是本着以實際出發,實事求是的態度,力求提高開發效率(我自己都是第一個使用者),目前來看反響不錯。但是隨着前端和後端技術的不斷變革,尤其是前端,目前大環境已經是前後端完全分離為主的開發模式,在這樣的大環境和必然趨勢之下,傳統的MVC就顯得有些落伍了。在這樣的背景下,一款前後端分離的.NET開發框架就顯得尤為必要,由此便定了框架的升級目標: 前後端分離 。 首先後端技術的選擇,從目前的數據來看,.NET Core的發展遠遠快於.NET Framework,最簡單的分析就是Colder.Fx.Core.AdminLTE發布比Colder.Fx.Net.AdminLTE晚,但是星星卻後來居上而且比前者多30%,並且這個差距在不斷擴大,由點及面的分析可以看出我們廣大.NET開發人員學習的熱情和积極向上的態度,並不是某些人所認為的那麼不堪( 走自己的路,讓別人說去吧 )。大環境上微軟积極擁抱開源,大力發展.NET Core, 可以說前途一片光明。因此後端決定採用 .NET Core3.0 ,不再浪費精力去支持.NET Framework。 然後是前端技術選擇,首選是三大js框架選擇,也是從實際出發,Vue相對其它而言更加容易上手,並且功能也毫不遜色,深得各種大小公司喜歡,如果偏要說缺點的話,那就是對TS支持不行,但是即將發布Vue3.0肯定會改變這一缺陷。選擇了Vue之後,然後就是UI框架的選擇了,這裏的選擇更多了,我選擇了Ant Design Vue,理由便是簡潔方便,十分符合我的設計理念。 技術選型完畢之後便...

台北市住宅、社區建創儲能設備 最高可獲600萬元補助

為了推廣分散式發電,台北市環保局預計補助1億元供住宅社區設置創能、儲能設備,計有3種方案可供選擇。環保局說明,每案補助額度不超過建制總經費49%,社區每案最高可獲200萬至600萬元補助,住宅每案補助上限100萬元,5月1日起開放申請。 環保局說明,台北市溫室氣體排放量7成以上來自住商部門,其中以使用電力造成間接溫室氣體排放為大宗,台北市平均年用電量約159.86億度,1度電約等同排放0.5公斤二氧化碳,若想達成2050年淨零排放目標,僅靠節能減碳無法達成,必須發展綠色創能、儲能,並且參考歐洲、日本的做法,採分散式發電方式,推廣到社區、住家、商辦,達到供電自給自足目標。 因此,環保局推出「台北市住宅社區創能儲能及節能補助計畫」,補助對象為台北市轄內房屋所有權人及社區管理委員會,補助方案共計3種,每一申請人或每一場址僅能獲1次補助,每案補助額度不超過建置總經費49%為限,5月1日到7月31日開放申請,但補助經費用完即停止申請。 環保局說明,方案A補助對象以社區為主,公共區域申請創能儲能及節能項目,每案補助上限新台幣600萬元;方案B分為住宅或社區公共區域申請創能搭配儲能項目(創能或儲能方案不得單獨申請),社區每案補助上限新台幣400萬元,住宅每案補助上限100萬元。方案C補助對象也是社區,公共區域申請節能項目,每案補助上限新台幣200萬元。 網頁設計 最專業,超強功能平台可客製,窩窩以「數位行銷」「品牌經營」「網站與應用程式」「印刷品設計」等四大主軸,為每一位客戶客製建立行銷脈絡及洞燭市場先機,請問 台中電動車 哪裡在賣比較便宜可以到台中景泰電動車門市去看看總店:臺中市潭子區潭秀里雅潭路一段102-1號。 電動車補助 推薦評價好的 iphone維修 中心擁有專業的維修技術團隊,同時聘請資深iphone手機維修專家,現場說明手機問題,快速修理,沒修好不收錢住家的頂樓裝 太陽光電 聽說可發揮隔熱功效一線推薦東陽能源擁有核心技術、產品研發、系統規劃設置、專業團隊的太陽能發電廠商。 網頁設計 一頭霧水該從何著手呢? 回頭車 貨運收費標準宇安交通關係企業,自成立迄今,即秉持著「以誠待人」、「以實處事」的企業信念 台中搬家公司 教你幾個打包小技巧,輕鬆整理裝箱!還在煩惱搬家費用要多少哪?台中大展搬家線上試算搬家費用,從此不再擔心「物品怎麼計費」、「多...