LeetCode-926 flip-string-to-monotone-increasing 字串翻轉到單調遞增
阿新 • • 發佈:2018-11-07
題目連結
LeetCode 周賽 107場 B題
https://leetcode-cn.com/contest/weekly-contest-107/problems/flip-string-to-monotone-increasing/
題意
中文題,這個遞增允許不變,例如全0或者全1也是按照遞增處理。
題解
智障了= =竟然拖很長時間才做出來。剛開始想使用暴力(絕壁TLE),想到了使用DFS,即從第一個字元開始,如果是0,那麼有翻轉或者不翻轉兩種可能,再往下搜尋時判定上一位是0還是1,如果是0那麼這一位可以翻轉可以不翻轉,如果是1,那麼這一位就只能翻轉。
這樣DFS而不考慮剪枝的話是TLE的。後來想了一下,全0或者全1的情況排除,只剩下一種情況:以i點為軸,左邊全為0,右邊全為1。這樣在極限的情況下就是全0或者全1的情況。那麼可以這樣考慮:以i為軸,i左邊所有的數1翻轉為0,右邊的數0翻轉成1。這樣在程式碼上,可以先遍歷一次字串,統計0或者1的總數,第二次遍歷,建立一個數組,儲存該點左邊有幾個0或者1。第三次遍歷,根據上面獲得的變數利用數學推導(解一元方程而已)計算出來翻轉次數。這樣在O(n)的時間複雜度上解決該問題。
Java 程式碼
class Solution { public static int Min(int a,int b){ return a > b ? b : a; } public int minFlipsMonoIncr(String S) { int len = S.length(); int num0 = 0; int[] left0 = new int[len]; for(int i = 0;i < len;i++){ if(S.charAt(i) == '0'){ num0++; } } if(S.charAt(0) == '0'){ left0[0] = 1; }else{ left0[0] = 0; } for(int i = 1;i < len;i++){ left0[i] = left0[i-1]; if(S.charAt(i) == '0'){ left0[i]++; } } int ans = Min(num0,(len - num0)); for(int i = 0;i < len;i++){ int now = i+1+num0-2*left0[i]; ans = Min(ans,now); } return ans; } }