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;
}
};

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值