• 1888. 使二进制字符串字符交替的最少反转次数


    我们可以将所有类型 (2) 的操作安排在类型 (1) 的操作之前。因为类型 (2) 的操作是反转任意一个字符,而类型 (1) 的操作只会改变字符的相对顺序,不会改变字符的值。

    (n) 是偶数时,交替字符串只可能为 (0101cdots 01) 或者 (1010 cdots 10) 的形式。

    如果 (n) 是奇数,那么交替字符串为 (0101 cdots 010) 或者 (1010 cdots 101) 的形式。

    我们首先考虑 (0101 cdots 010),如果在所有类型 (2) 的操作完成后,(s) 可以通过类型 (1) 的操作得到该字符串,那么:

    要么 (s) 就是 (0101 cdots 010)

    要么 (s)(01 cdots 010 | 01 cdots 01) 的形式,或者是 (10 cdots 10|01 cdots 010) 的形式。这里我们用竖线 (|) 标注了类型 (1) 的操作,在 (|) 左侧的字符通过类型 (1) 的操作被移动到字符串的末尾,最终可以得到 (0101 cdots 010)

    因此,(s) 要么是一个交替字符串(即 (0101 cdots 010)),要么由两个交替字符串拼接而成,其中左侧的交替字符串以 (0) 结尾,右侧的交替字符串以 (0) 开头。

    同理,如果我们考虑 (1010 cdots 101),那么 ss 要么就是 (1010 cdots 101),要么由两个交替字符串拼接而成,其中左侧的交替字符串以 (1) 结尾,右侧的交替字符串以 (1) 开头。

    我们用 ( extit{pre}[i][j])表示对于字符串的前缀 (s[0..i]),如果我们希望通过类型 (2) 的操作修改成「以 (j) 结尾的交替字符串」,那么最少需要的操作次数。这里 (j) 的取值为 (0)(1)。根据定义,有递推式:

    [egin{cases} extit{pre}[i][0] = extit{pre}[i-1][1] + (s[i] =='1') \ extit{pre}[i][1] = extit{pre}[i-1][0] + (s[i] == '0') end{cases} ]

    同理,我们用 ( extit{suf}[i][j]) 表示对于字符串的后缀 (s[i..n-1]),如果我们希望通过类型 (2) 的操作修改成「以 (j) 开头的交替字符串」,那么最少需要的操作次数。这里 (j) 的取值为 (0)(1),同样有递推式:

    [egin{cases} extit{suf}[i][0] = extit{suf}[i+1][1] + mathbb{I}(s[i], 1) \ extit{suf}[i][1] = extit{suf}[i+1][0] + mathbb{I}(s[i], 0) end{cases} ]

    答案可以为 ( extit{pre}[n-1][0])或者 ( extit{pre}[n-1][1]),对应着将 (s) 本身变为一个交替字符串;

    如果 (n) 是偶数,我们无需求出 ( extit{suf})

    如果 (n) 是奇数,那么答案还可以为 ( extit{pre}[i][0] + extit{suf}[i+1][0]) 以及 ( extit{pre}[i][1] + extit{suf}[i+1][1]),对应着将 (s) 变为两个交替字符串的拼接。

    所有可供选择的答案中的最小值即为类型 (2) 的操作的最少次数。

    class Solution {
    public:
        static const int N=1e5+10;
        int pre[N][2],suf[N][2];
        int minFlips(string s) {
            int n=s.size();
    
            for(int i=1;i<=n;i++)
            {
                pre[i][0]=pre[i-1][1]+(s[i-1] == '1');
                pre[i][1]=pre[i-1][0]+(s[i-1] == '0');
            }
    
            int ans=min(pre[n][0],pre[n][1]);
    
            if(n & 1)
            {
                for(int i=n;i;i--)
                {
                    suf[i][0]=suf[i+1][1]+(s[i-1] == '1');
                    suf[i][1]=suf[i+1][0]+(s[i-1] == '0');
                    ans=min(ans,pre[i][0]+suf[i+1][0]);
                    ans=min(ans,pre[i][1]+suf[i+1][1]);
                }
            }
    
            return ans;
        }
    };
    
  • 相关阅读:
    Apache服务器安装-apache已经卸载,如何删除注册在系统的服务
    REST&RESTFUL
    SQL注入漏洞产生的原因是什么?怎么防止?XSS呢?
    git的常用命令
    Linux服务器上安装MySql数据库(默认安装,密码为空),首次使用需要修改密码
    iOS-UI控件优化
    iOS isa指针
    iOS Runtime 运行时
    程序员面试总结
    迷宫寻宝(一)(bfs)
  • 原文地址:https://www.cnblogs.com/fxh0707/p/14859900.html
Copyright © 2020-2023  润新知