1. 程式人生 > >leetcode 926. 將字串翻轉到單調遞增(機智題)

leetcode 926. 將字串翻轉到單調遞增(機智題)

題目:

一個只有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;
}
};