leetcode 926. 將字串翻轉到單調遞增(機智題)
阿新 • • 發佈:2018-11-21
題目:
一個只有0,1組成的字串,每一次操作可以把一個字元從0到1或者從1到0,求最少操作次數形成單調不減字串
思路:
一開始用DP,果斷超時。。。。。一直以為1s可以跑1e9,結果只能跑1e8
因為只有兩種形式的字元,到最後肯定後面部分是1,前面部分是0,當然可以全0全1的情況。那麼我們只需要找到這個分界點,使得包括分界點左邊全是0,右邊全是1.怎麼找分界點呢?我們可以統計前面部分1的個數,和從後往前統計0的個數,然後遍歷每一個點,計算這個點左邊1的個數和右邊0的個數,這就是我們需要操作的次數,因為我們需要把左邊的1全變為0,右邊的0全變為1.找其中的最小值就行了。統計0,1個數和遍歷分界點為線性時間複雜度。
程式碼:
class Solution { public: int minFlipsMonoIncr(string S) { int len = S.length(); if(len==0)return 0; int one[20000+50]; //統計從0到i點的1的個數 int zero[20000+50];//統計i到結尾的0的個數 memset(one,0,sizeof(one)); memset(zero,0,sizeof(zero)); if(S[0]=='1')one[0] = 1; else one[0] = 0; for(int i=1;i<len;i++){ if(S[i]=='1')one[i] = one[i-1] + 1; else one[i] = one[i-1]; } if(S[len-1]=='0')zero[len-1] =1; else zero[len-1] = 0; for(int i=len-1;i>=0;i--){ if(S[i]=='0'){ zero[i] = zero[i+1] +1; } else zero[i] = zero[i+1]; } int ma = zero[0]; zero[len] = 0; for(int i=0;i<len;i++){ //遍歷分界點 ma = min(ma,one[i]+zero[i+1]); } // for(int i=0;i<len;i++)cout<<dp[i]<<" ";cout<<endl; // cout<<len<<endl; return ma; } };