Leecode 第88場比賽回顧
一、背景
我大概是 2015 年聽說的 Leecode 的,然後開始刷題,刷了一大部分,所有題都提交到 github 上了。
地址在這裡(點選底部原文可以點選連結): https://github.com/tiankonguse/leetcode-solutions
轉眼間,已經過了四年了。
leecode 上的題也翻了好幾倍了。
今年開始繼續維護這個 github 專案,把其他題也做了,補上來。
今天做了第88場比賽,有四道題,下面分別來看看吧。
二、迴圈移動字串
對於字串的迴圈移動,大家應該都聽說過。
對於字母表有26個,迴圈移動一次,a 將會變成 b,b 將會變成 c,依次遞推下去,最後的 z 將會變成 a 。
如果迴圈移動 n 次,就是重複上面的操作 n 次。
如果僅僅是這樣,那就太簡單了。
所以題意稍微加強了一些:對於長度為 len
的字串,有 len
次操作, 每次操作都是對前 i
個字元迴圈右移 shifts[i]
次。
面對這個加強的題意,如果我們單獨看每個字元的話,就會發現,題意是對每個位置的字元迴圈移動了多批,每批移動若干次。
所以我們可以統計出每個字元移動的次數,然後進行移動轉化即可。
這裡面有個注意點是:題意要求每次操作對前 i
個字元迴圈移動,如果我們從前到後分別計算移動次數,複雜度就是 O(n^2)
了。
而我們從後到前的話,就可以累積加了,這樣複雜度就是 O(n)
了。
三、離自己距離最近的最大距離
這道題的意思是有n位置,有些位置有人坐,有些位置沒人坐,求我們挑一個位置,使得離理解距離最近的那個人的距離最大。
面對這個題意,我們需要分三種情況:坐最前面,坐最後面,坐中間。
坐最前面和最後面時,空位置的個數就是距離,而坐中間時,由於左邊和右邊都有人,最大距離就是最大空位置的二分之一了。
當然,有一些邊界情況,比如沒有最前面、沒有最後面、沒有中間等。
考慮著三種情況後基本上就沒什麼問題了。
四、比自己富但是最安靜的人
這道題算是圖論題了。
給一個無環有向圖,代表兩個人誰比誰富有。
每個有有一個不同的安靜值,求所有人的比自己富有但最安靜的那個人。
對於這道題,如果我們把這個有向圖畫出來,並手動在圖上計算出每個人的答案,我們大概就知道怎麼做這道題了。
對於每個人,我們只需要計算 所有比這個人直接富有的人的安靜值答案,取最小值即可。
這裡的直接富有代表兩個人之間有條邊。
如果這樣暴力做的話,複雜度是 O(n^2)
。
觀察發現,很多人的最優安靜值我們重複計算了,所以做一個標記,算過的不再算了,這樣複雜度就是 O(n)
了。
五、矩陣面積並集
這道題含義很簡單,給一堆矩形,求面積的並集。
並集意味著這些矩形會相互覆蓋,考慮到四個點座標系的複雜性,兩個矩形的關係有很多很多種情況。
所以我們需要換個思路來看這個問題了。
第一種思路是一個個掃描矩形,每當矩形相交時,我們就把矩形拆分成互相不相交的小矩形。
但是考慮到極端情況,我們可能拆分出 f(n) = f(n-1) + k*n = O(n^2)
的小矩形來,而由於是邊拆分邊比較,時間複雜度就是 O(n^3)
了。
當然,對於這道題,這個複雜度可以過,但是實現還是相當複雜的,尤其是拆分矩形的邏輯,分的情況還是蠻多的。
而另一個思路是掃面法。
比如說我們有一個垂直於x座標軸的一根豎線,開始的時候在負無窮。
然後我們開始向正方向移動,每遇到一個矩形,我們就加上這個矩形的面積(只加新增的部分)。
這個可以理解為高階版的俄羅斯方塊,每次下落的時候不是完全的挨著,而是可以部分重疊。
這個重疊部分就是和之前累積矩陣的交集。
這是再看我們的豎線,發現有特徵了:不同的高度,可能向左累積了不同的長度矩形。
所以我們需要記錄每個位置向左累積的長度。
這裡唯一的問題是點太多,無法表示所有的點。
面對矩形的數值範圍比較大,我們發現矩形個數比較少,我們可以不記錄點,而記錄線段。線段的端點就是矩形的Y座標。
為了方便表示,我們需要提前計算出所有的線段,並儲存在陣列中,這個過程我們稱為座標離散化(不同座標進行編號)。
離散化後,我們就可以就可以只記錄編號了,一個編號代表一個區間,這樣就可以表示整根豎線向左突出的距離了。
六、最後
這四道題整體還算簡單,有字串、計算、圖論、幾何四種題型,大家可以練習一下。
由於我好久沒做 Leecode 了,做最後一題時,提交怎麼都編譯不過,浪費不少時間。 接下來就是搭建環境了,有了順暢的環境,開發、編譯、測試就可以一氣呵成了。
目前我的環境大概如下,後續會加一個 DIFF
的功能,返回 YES
或 NO
來快速判斷樣例是否通過。
-EOF-