LeetCode/将字符串翻转到单调递增
如果一个二进制字符串,是以一些 0(可能没有 0)后面跟着一些 1(也可能没有 1)的形式组成的,那么该字符串是单调递增的
给你一个二进制字符串 s,你可以将任何 0 翻转为 1 或者将 1 翻转为 0
返回使 s 单调递增的最小翻转次数
1. 暴力法
遍历每一个位置,计算将该位置左侧全部置0,右侧全部置1所需要的翻转次数
最后求取对应翻转最小次数
暴力法
class Solution {
public:
int minFlipsMonoIncr(string s) {
int n = s.size();
int res = INT_MAX;
for(int i=0;i<=n;i++){
int sum = 0;
for(int j=0;j<i;j++)
sum = sum + s[j]-'0';
for(int j=i;j<n;j++)
sum = sum + '1'-s[j];
res = min(res,sum);
}
return res;
}
};
2. 暴力法优化
事先计算出每个位置左右侧置0置1需要的翻转次数,避免重复计算
class Solution {
public:
int minFlipsMonoIncr(string s) {
int n = s.size();
int res = INT_MAX;
//因为很多重复计算,所以先把和计算出来
vector<int> left(n+1);//left[i]存储i左侧置零需要的次数
vector<int> right(n+1);//right[i]存储i右侧置一需要的次数
left[0]=0;//位于最左侧无需修改任何值为0
for(int j=1;j<=n;j++)
left[j] = left[j-1] + s[j-1]-'0';
right[n]=0;//由于最右侧无需修改任何值为1
for(int j = n-1;j >=0;j--)
right[j] = right[j+1] + '1'-s[j];
for(int i=0;i<=n;i++)
res = min(res,right[i]+left[i]);
return res;
}
};
3. 动态规划
dp[i]为使得0~i递增的最小翻转数
状态转移方程为
dp[i]=dp[i-1] if s[i]='1' //无需翻转
dp[i]= min(dp[i-1]+1,count) if s[i]='0' //count即把全部值变成0
class Solution {
public:
int minFlipsMonoIncr(string s) {
int dp = 0;
int count = 0;
for(int i=0;i<s.size();i++){
if(s[i]=='0')
dp = min(dp+1,count);
else count++;
}
return dp;
}
};