Re: [閒聊] 每日LeetCode已回收

看板Marginalman作者 (麵包屌)時間2年前 (2023/01/17 20:16), 編輯推噓1(101)
留言2則, 2人參與, 2年前最新討論串195/719 (看更多)
926. Flip String to Monotone Increasing 給你一個只有 0 和 1 的 string s,問你最少要翻轉幾次才能把它變為遞增 翻轉:把某個 0 變成 1 或者是把某個 1 變成 0 Example 1: Input: s = "00110" Output: 1 翻轉成 00111 Example 2: Input: s = "010110" Output: 2 翻轉成 000111/011111 Example 3: Input: s = "00011000" Output: 2 翻轉成 00000000 思路: 1.要讓 string 是遞增就必須是一串 0 接著一串 1 也就是說對於某個 index = i, s[:i] 全部都是 0, s[i:] 全部都是 1 我們就去遍歷所有 i, 看看要讓 s[:i] 翻轉成 0 的次數加上 s[i:] 翻轉成 1 的次數 在哪個 i 時會是最小 2.要把 s[:i] 翻轉成 0 的次數其實就是算 s 的 prefix sum, O(n)解決 算完全部後再反著做 s[i:], iterate i = len(s)-1 ~ 0 然後一邊檢查最小值就好 時間 O(n) 空間 O(n) 3.看了討論區有種更好的做法是用類似 dp 的概念 假設已經知道要把 s[:i] 翻轉成遞增的最小次數 n 了 那 s[:i+1] 就有兩種可能 一種是 s[i] 變成/保持 1, 這種狀況下可以直接拿 n 來用 因為 s[:i] 翻轉 n 次已經變成遞增了, s[i] 的 1 可以直接接在後面 這種情況下最佳解就會是 n + (s[i] == 0), 也就是如果 s[i] == 0 要把他轉成 1 另一種是 s[i] 變成/保持 0, 這種狀況下 n 就沒用了 因為 s[:i] 轉完後有可能是 1 結尾, s[i] 的 0 不能接 所以這裡最佳解就只能是把 s[:i] 和 s[i] 全部都變成 0, 也就是 prefix sum 最後再比兩種狀況哪種比較小就好 這種做法比剛剛那種好的原因是可以只 iterate i 一次, 也不用記整個 prefix sum 時間一樣是 O(n) 空間變成 O(1) Python code: class Solution: def minFlipsMonoIncr(self, s: str) -> int: one = opt = 0 for c in s: one += (c == '1') opt = min(one, opt + (c == '0')) return opt -- 蛤? -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 111.251.202.128 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/Marginalman/M.1673957796.A.801.html

01/17 20:17, 2年前 , 1F
大師
01/17 20:17, 1F

01/17 22:17, 2年前 , 2F
大師
01/17 22:17, 2F
文章代碼(AID): #1Znf6aW1 (Marginalman)
討論串 (同標題文章)
文章代碼(AID): #1Znf6aW1 (Marginalman)