题目描述:
huaji有一个 01
序列,每次可以对其中的某一位取反(0变1,1变0)。
求最少翻转其中的几位可以使得该序列变为非递减序列。
输入格式:
第一行输入一个整数 nn (1≤n≤1e6)。
第二行输入一个长度为 nn 的且仅包含 0
和 1
的字符串。
输出格式:
输出一个整数,为该序列变为非递减序列的最少操作次数。
样例输入:
6
010110
样例输出:
2
本题较易获得的一种思路,暴力求解,我们知道结果无论如何都是一个前面为0后面为1的序列,所以我们只需要列出所有情况就可以了。
拿样例来看,长度一共为6,所有的情况也就是6种,000001,000011,000111,001111,011111,111111,只有这六种情况。所以暴力的复杂度也只有o(n)并不会超时,所以直接写出来就好,至于每一种情况,我们只要拿出一个点为分界点,计算这个数已经前面由多少个1,这个数的后面有多少个0就可以了。
下面是代码:
#include<iostream>
const int N = 1e6+5;
int f[N];
using namespace std;
int main()
{
int n;
cin >> n;
string ch ;
cin >> ch;
if(n == 1)
{
cout << 0 << endl;
return 0;
}
for(int i = 1 ; i <= n ; i++)
{
f[i] = f[i-1] + (ch[i - 1 ] - '0'); // 1 的个数
}
int ans = 0x3f3f3f3f;
for(int i = 1 ; i <= n ; i ++)
{
if( (n - i - (f[n] - f[i])) + f[i] < ans ) ans =(n - i - (f[n] - f[i])) + f[i] ;
//(n - i - (f[n] - f[i]))表示后面的0的个数,f[i]表示前面的1的个数。
}
cout << ans << endl;
return 0;
}