5.16周测

A. 01 分界最小翻转

题目描述

给定一个仅由字符 '0' 和 '1' 组成的字符串,你可以对字符串中的任意一个字符执行任意次翻转操作:将 '0' 变为 '1',或将 '1' 变为 '0'。每次翻转计为 1 次变换。

要求通过最少的翻转次数,使得字符串满足所有的 '0' 都严格出现在所有的 '1' 的前面。允许最终字符串中不存在 '0'(全 1),也允许不存在 '1'(全 0)。请计算并输出这个最少翻转次数。

输入格式

输入包含多组测试数据,每组数据占一行,为一个仅由 '0' 和 '1' 组成的非空字符串。

输入数据直到文件结束(EOF)为止。

输出格式

对于每组测试数据,输出一行一个整数,表示满足要求的最少翻转次数。

数据范围

单个字符串长度 n:1≤n≤1051≤n≤10^51≤n≤105

所有测试数据的字符串总长度不超过 10610^6106

样例输入输出

  • 输入样例

0101

1100

10

01

0000

1111

  • 输出样例

1

2

1

0

0

0

  • 样例解释

输入 "0101":最优方案为翻转第 3 位的 '0' 为 '1'(得到 "0111"),或翻转第 2 位的 '1' 为 '0'(得到 "0001"),均只需 1 次翻转。

输入 "1100":最优方案为翻转两个 '0' 为 '1'(全 1)或翻转两个 '1' 为 '0'(全 0),均需 2 次翻转。

输入 "10":必须翻转其中一个字符,最少 1 次。

输入 "01":本身已满足要求,无需翻转。

全 0 或全 1 字符串:天然符合要求,翻转次数为 0。


思路:枚举 + 统计前缀

n为字符串s的长度

定义以边界为i翻转的字符串:
s中第0个字符到第i个字符为0,第i+1个字符到第n个字符为1

特别的:

  • i = 0:以s最左边(第一个字符s[0]前面)为翻转边界,最终翻转为全为1的字符串
  • i = n:以s[n - 1]为翻转边界,最终翻转为全为0的字符串

total_ones表示s中1的总数
cur_ones:表示第1个字符到第i个字符1的总数

定义变量min_flips = n - total_ones:初始化为以i = 0为边界所需的翻转次数

以i为边界翻转的所需的次数:
flips = 前i个字符中1的个数 + 后n-i个字符中0的个数
flips = cur_ones + n - total_ones - (i - cur_ones)

  • 第一次遍历,统计total_ones
  • 第二次遍历,枚举所有边界,取最小值

C++

cpp 复制代码
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
    //优化
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    string s;
    while (cin >> s)
    {
        int n = s.size();
        //定义分界点i:第0个字符(不存在)到第i个字符为0,第i+1个字符到最后一个字符为1
        //i = 0:全为1的字符串
        //i = n:全为0的字符串

        int total_ones = 0;
        //首次遍历:统计1的个数
        for (auto ch : s)
            if (ch == '1')
                total_ones++;
        
        int min_flips = n - total_ones;//初始化为i=0的情况

        int cur_ones = 0;//第0个字符到第i个字符的1的总数
        //再次遍历:枚举边界,求最小翻转次数
        for (int i = 1; i <= n; ++i)
        {
            //统计第0个字符到第i个字符1的总数
            if (s[i - 1] == '1')
                cur_ones++;
            //套用公式
            int flips = cur_ones + n - total_ones - (i - cur_ones);
            min_flips = min(min_flips, flips);   
        }
        cout << min_flips << '\n';//性能优化:读到EOF再刷新缓冲区
    }
}
相关推荐
半杯咖啡半行码1 小时前
C++11核心特性详解:从C++11到C++20 的现代C++指南
开发语言·c++
All for pursuit.2 小时前
【位运算-3】136.只出现一次的数字
数据结构·c++·算法·leetcode
C++ 老炮儿的技术栈4 小时前
std::atomic 是什么
linux·c语言·网络·c++·visual studio
All for pursuit.4 小时前
【完结】LeetCodeHot100题 详细解题过程及代码汇总
数据结构·c++·算法·leetcode
重生之小比特5 小时前
【算法拾光】双指针|移动零 + 复写零
数据结构·c++·算法
多弗朗皮卡丘5 小时前
C++异常
开发语言·c++·异常
米糕闯编程5 小时前
鱼香ros2(十七)C++小海龟巡逻
开发语言·c++·机器人·ros2·服务·小海龟
栈帧之外6 小时前
【C++】红黑树实现
开发语言·c++
程序员老陆6 小时前
C++中同一个回调函数被多个设备并发调用:并发问题不在“函数”,而在“状态”
开发语言·c++·程序设计
辛苦才能6 小时前
C++ unordered_map/set 深度解析:快在O(1),输在无序,与map/set怎么选
c++·哈希算法·散列表