LeetCode 926. 将字符串翻转到单调递增

926. 将字符串翻转到单调递增

 

【DP】开一个int[n+1][2]的dp数组其中n是字符串长度,2是指0和1,dp[i][0]表示到达第i个,并且保证i位置为0的情况下需要的最小的翻转数,dp[i][1]表示到达第i个,并且保证第i个是1的况下的最小翻转数,于是转移公式就成了:

(1)当第i个为0的情况下:

dp[i + 1][0] = dp[i][0]. 只能从0转移

dp[i + 1][1] = min(dp[i][0], dp[i][1]) + 1. 可以从0和1转移,因为要让当前变成1,所以还要+1

(2)当第i个为1的情况下:

dp[i + 1][0] = dp[i][0] + 1. 只能从0转移,并且要把当前的1翻转成0

dp[i + 1][1] = min(dp[i][0], dp[i][1])     从0和1转移都行,并且不用变第i个字符

class Solution {

    // DP 7:39

    public int minFlipsMonoIncr(String s) {
        int n = s.length();
        int[][] dp = new int[n + 1][2];
        for(var i = 1; i <= n; i++){
            char c = s.charAt(i - 1);
            if(c == '0'){
                dp[i][0] = dp[i - 1][0];
                dp[i][1] = Math.min(dp[i - 1][0], dp[i - 1][1]) + 1;
            }else{
                dp[i][0] = dp[i - 1][0] + 1;
                dp[i][1] = Math.min(dp[i - 1][0], dp[i - 1][1]);
            }
        }
        return Math.min(dp[n][0], dp[n][1]);
    }
}

【前缀和】用前缀和来统计到达i时1的个数,字符串长度为n,1的总个数为m,那么0的个数就是n-m个,然后假设以i处划分i之前都是0,i之后是1。那么前面的1的个数都要变为0,后面的0的个数为(n - i) - (m - pre[i]),这些0要全部变为1,这样遍历一遍取最小值即可。

class Solution {
    public int minFlipsMonoIncr(String s) {
        // 前缀和 7:55 10

        int n = s.length(), i;
        int[] pre = new int[n + 1];
        for(i = 1; i <= n; i++){
            if(s.charAt(i - 1) == '1') pre[i] = pre[i - 1] + 1;
            else pre[i] = pre[i - 1];
        }
        int ans = n;
        for(i = 0; i <= n; i++){
            int t = pre[i] + (n - i - pre[n] + pre[i]);
            ans = Math.min(t, ans);
        }
        return ans;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值