Leetcode 【485、1004撑碴、1052】

問(wèn)題描述:【Array】485. Max Consecutive Ones
解題思路:

因?yàn)橐易铋L(zhǎng)連續(xù) 1 子數(shù)組的長(zhǎng)度撑教,所以我們只需要遍歷一次,記錄每段連續(xù) 1 的長(zhǎng)度醉拓;如果遇到 0伟姐,就更新當(dāng)前最大長(zhǎng)度,然后當(dāng)前長(zhǎng)度清零亿卤,繼續(xù)向后遍歷愤兵。時(shí)間復(fù)雜度為 O(n)。

Python3 實(shí)現(xiàn):
class Solution:
    def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
        max_ = tem = 0
        for i in range(len(nums)):
            if nums[i] == 0:
                max_ = max(max_, tem)  # 更新當(dāng)前最大長(zhǎng)度
                tem = 0
            else:
                tem += 1
        return max(max_, tem)

問(wèn)題描述:【Array】487. Max Consecutive Ones

收費(fèi)暫時(shí)做不了 hhh~ 題目是最多改變其中 1 個(gè) 0 變成 1排吴,然后求最長(zhǎng)連續(xù) 1 子數(shù)組的長(zhǎng)度秆乳。可以采用滑動(dòng)窗口的做法钻哩,在下面的 1004 題有具體的解法屹堰,代碼和 1004 完全一樣。


問(wèn)題描述:【Sliding Window】1004. Max Consecutive Ones III
解題思路:

這道題是最多改變 K 個(gè) 1 變成 0街氢,然后求最長(zhǎng)連續(xù) 1 子數(shù)組的長(zhǎng)度扯键。很容易想到滑動(dòng)窗口的思路(487 做法和本題做法一致,只不過(guò) 487 中 K = 1):

我們來(lái)定義本題的滑動(dòng)窗口:因?yàn)榭隙▽⑺?K 個(gè) 0 改成 1 才能獲得最大長(zhǎng)度珊肃,因此滑動(dòng)窗口中記錄包含 K 個(gè) 0 之后的最長(zhǎng)連續(xù) 1 子數(shù)組荣刑。注意到這個(gè)滑動(dòng)窗口的大小是不固定的,因此伦乔,我們?cè)诨瑒?dòng)的過(guò)程中厉亏,要記錄滑動(dòng)窗口的起始位置(終止位置不用記,因?yàn)榻K止位置就是當(dāng)前遍歷的位置)烈和。

如何更新滑動(dòng)窗口呢爱只?如果我們的滑動(dòng)窗口中已經(jīng)有 K 個(gè) 0 了,后面又遇到一個(gè) 0招刹,那么我們就要移動(dòng)滑動(dòng)窗口虱颗,根據(jù)滑動(dòng)窗口的起始位置找到窗口中最前面的 0,然后這個(gè) 0 的下一個(gè)位置就是新滑動(dòng)窗口的起始位置蔗喂。注意忘渔,在這個(gè)過(guò)程中,還要減小滑動(dòng)窗口的長(zhǎng)度缰儿。

這樣畦粮,我們只需要遍歷 1 次,不斷更新最大長(zhǎng)度,就能得到結(jié)果宣赔。

注意:剛開(kāi)始時(shí)滑動(dòng)窗口中 0 的個(gè)數(shù)如果小于 K预麸,我們只拓展窗口,不更新窗口的起始位置(最開(kāi)始的起始位置為 0)儒将。

Python3 實(shí)現(xiàn):
class Solution:
    def longestOnes(self, A: List[int], K: int) -> int:
        sliding_window = 0  # 滑動(dòng)窗口
        begin = 0  # 滑動(dòng)窗口的起始位置
        nums0 = 0  # 滑動(dòng)窗口中0的個(gè)數(shù)
        max_ = 0
        for i in range(len(A)):
            sliding_window += 1  # 拓展窗口長(zhǎng)度
            if nums0 < K:  # 滑動(dòng)窗口中 0 的個(gè)數(shù)小于 K吏祸,只拓展窗口
                if A[i] == 0:
                    nums0 += 1
            elif nums0 == K:
                if A[i] == 0:  # 如果再有 0 出現(xiàn),更新滑動(dòng)窗口
                    while A[begin] == 1:  # 找到滑動(dòng)窗口中第1個(gè)0的位置
                        begin += 1
                        sliding_window -= 1
                    begin += 1  # 新滑動(dòng)窗口的起始位置
                    sliding_window -= 1
            max_ = max(max_, sliding_window)  # 更新最大長(zhǎng)度
        return max_

問(wèn)題描述:【Sliding Window钩蚊、DP贡翘、Array】1052. Grumpy Bookstore Owner
解題思路:

方法1(暴力 O(N^2),TLE):

  • 根據(jù) customers 和 grumpy 數(shù)組砰逻,可以統(tǒng)計(jì)出不使用 X 技巧能得到的一個(gè)初始的滿意度總和鸣驱;
  • 再考慮使用 X 技巧,對(duì)于每個(gè)位置蝠咆,將長(zhǎng)度為 X 的窗口中 grupmy[i] == 1 的 custpmers[i] 也加入到初始滿意度中踊东,然后更新最大滿意度。

這樣刚操,時(shí)間復(fù)雜度為 O(N*X)闸翅,由于 X 也可能達(dá)到 N 的長(zhǎng)度級(jí)別,因此為 O(N^2)菊霜,超時(shí)缎脾。

方法2(DP O(N^2),勉強(qiáng) AC):

嘗試了一下動(dòng)態(tài)規(guī)劃占卧,雖然時(shí)間復(fù)雜度還是 O(N^2),但勉強(qiáng) AC 了联喘。DP 思路如下:

  • 用 dp1[N] 記錄不使用 X 技巧的累加初始滿意度华蜒,dp2[N] 記錄使用 X 技巧的最大滿意度,最后 dp2[-1] 就是答案豁遭;
  • dp1[N] 的狀態(tài)轉(zhuǎn)移方程很容易 dp1[i] = (dp1[i-1] + customers[i-1]) if grumpy[i-1] == 0 else dp1[i-1]叭喜;
  • dp2[N] 的狀態(tài)轉(zhuǎn)移方程為:dp2[i] = (dp2[i-1] + customers[i-1]) if grumpy[i-1] == 0 else max(dp2[i-1], dp1[i-X] + sum(customers[i-X:i])),含義是如果 grumpy[i-1] 為 0蓖谢,則老板不會(huì)生氣捂蕴,dp[i] 直接在 dp2[i-1] 的基礎(chǔ)上加上 customers[i-1] 就好;如果 grumpy[i-1] 為 1闪幽,則老板生氣啥辨,dp2[i] 的值取決于 dp2[i-1] (前面已經(jīng)生過(guò)氣)和 dp1[i-X] + sum(customers[i-X:i]) (當(dāng)前生氣,最大滿意度為前 dp1[i-X] 和這段 X 長(zhǎng)度大小的窗口中的數(shù)字之和)的最大值盯腌。
  • 初始時(shí) dp[i] 中 i < X溉知,無(wú)論生氣與否,dp2[i] = dp2[i-1] + customers[i-1],因?yàn)?X 技巧可以充分展現(xiàn)级乍。

但是舌劳,實(shí)際上這種做法還是 O(N*X) 的時(shí)間復(fù)雜度,但是竟然勉強(qiáng) AC 了(可能臉好吧)玫荣。

Python3 實(shí)現(xiàn)(DP):

class Solution:
    def maxSatisfied(self, customers: List[int], grumpy: List[int], X: int) -> int:
        N = len(customers)
        dp1 = [0] * (N + 1)  # 不使用 X 技巧的累加初始滿意度
        dp2 = [0] * (N + 1)  # 使用 X 技巧的最大滿意度
        for i in range(1, N + 1):
            if grumpy[i-1] == 0:
                dp1[i] = dp1[i-1] + customers[i-1]
            else:
                dp1[i] = dp1[i-1]
        for i in range(1, N + 1):
            if grumpy[i-1] == 0 or i-X-1 < 0:
                dp2[i] = dp2[i-1] + customers[i-1]
            else:
                dp2[i] = max(dp2[i-1], dp1[i-X] + sum(customers[i-X:i]))
        return dp2[-1]

方法3(Sliding Window O(N)甚淡,AC):

這也是一道經(jīng)典的利用滑動(dòng)窗口解決問(wèn)題的題目。

我們來(lái)定義本題的滑動(dòng)窗口:因?yàn)榭隙ó?dāng)技能 X 發(fā)揮時(shí)能獲得的滿意度最大捅厂,且這個(gè)窗口是連續(xù)的贯卦,因此窗口的大小是固定的。長(zhǎng)度為 X 的滑動(dòng)窗口中記錄增加的滿意度恒傻。

  • 先求出不使用 X 技巧的初始滿意度脸侥;
  • 因?yàn)榇翱谥杏涗浭褂?X 技巧增加的滿意度,所以它等于窗口中 grumpy[i] 為 1 的所有 customers[i] 之和盈厘;
  • 窗口每次都向右移動(dòng)一位睁枕,剛開(kāi)始窗口大小小于 X,那么只要是 grumpy[i] == 1 就增加滿意度(因?yàn)榭梢猿浞职l(fā)揮 X 技巧)沸手;當(dāng)窗口大小等于 X 時(shí)外遇,滑動(dòng)過(guò)程中始終保持 X 長(zhǎng)度;
  • 當(dāng)窗口大小等于 X契吉,如果出現(xiàn)一個(gè) grumpy[j] == 1跳仿,則窗口增加滿意度 customers[j];同時(shí)捐晶,如果移出去的 grumpy[j-X] == 1菲语,那么滑動(dòng)窗口的滿意度要減去滿意度 customers[j-X];
  • 每次移動(dòng)窗口惑灵,都更新使用 X 技巧增加的滿意度的最大值山上;
  • 最后,初始滿意度加上使用 X 技巧增加的滿意度的最大值就是總的最大滿意度英支。

這樣佩憾,時(shí)間復(fù)雜度為 O(N)。

Python3 實(shí)現(xiàn)(Sliding Window):

class Solution:
    def maxSatisfied(self, customers: List[int], grumpy: List[int], X: int) -> int:
        N = len(customers)
        initial_satisfied = sum([customers[i] for i in range(N) if grumpy[i] == 0])  # 初始的滿意度
        sliding_window = 0  # 大小為X的滑動(dòng)窗口中保存增加的滿意度
        add_satisfied = 0  # 大小為X的滑動(dòng)窗口中增加的滿意度的最大值
        for i in range(N):
            if i < X and grumpy[i] == 1:  # 沒(méi)有達(dá)到窗口大小
                sliding_window += customers[i]
            elif i >= X:
                if grumpy[i] == 1:
                    sliding_window += customers[i]  # 滑動(dòng)窗口中增加當(dāng)前滿意度
                if grumpy[i-X] == 1:
                    sliding_window -= customers[i-X]  # 滑動(dòng)窗口移除滿意度
            add_satisfied = max(add_satisfied, sliding_window)
        return initial_satisfied + add_satisfied  # 兩者之和為最終滿意度
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末干花,一起剝皮案震驚了整個(gè)濱河市妄帘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌池凄,老刑警劉巖抡驼,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異肿仑,居然都是意外死亡婶恼,警方通過(guò)查閱死者的電腦和手機(jī)桑阶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)勾邦,“玉大人蚣录,你說(shuō)我怎么就攤上這事【炱” “怎么了萎河?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蕉饼。 經(jīng)常有香客問(wèn)我虐杯,道長(zhǎng),這世上最難降的妖魔是什么昧港? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任擎椰,我火速辦了婚禮,結(jié)果婚禮上创肥,老公的妹妹穿的比我還像新娘达舒。我一直安慰自己,他們只是感情好叹侄,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布巩搏。 她就那樣靜靜地躺著,像睡著了一般趾代。 火紅的嫁衣襯著肌膚如雪贯底。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,475評(píng)論 1 312
  • 那天撒强,我揣著相機(jī)與錄音禽捆,去河邊找鬼。 笑死飘哨,一個(gè)胖子當(dāng)著我的面吹牛胚想,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播杖玲,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼淘正!你這毒婦竟也來(lái)了摆马?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鸿吆,失蹤者是張志新(化名)和其女友劉穎囤采,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體惩淳,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蕉毯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年乓搬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片代虾。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡进肯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出棉磨,到底是詐尸還是另有隱情江掩,我是刑警寧澤,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布乘瓤,位于F島的核電站环形,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏衙傀。R本人自食惡果不足惜抬吟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望统抬。 院中可真熱鬧火本,春花似錦、人聲如沸蓄喇。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)妆偏。三九已至刃鳄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間钱骂,已是汗流浹背叔锐。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留见秽,地道東北人愉烙。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓叠纹,卻偏偏與公主長(zhǎng)得像搭伤,于是被迫代替她去往敵國(guó)和親候齿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鳞芙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容