题目链接
LeetCode 周赛 107场 B题
https://leetcode-cn.com/contest/weekly-contest-107/problems/flip-string-to-monotone-increasing/
题意
中文题,这个递增允许不变,例如全0或者全1也是按照递增处理。
题解
智障了= =竟然拖很长时间才做出来。刚开始想使用暴力(绝壁TLE),想到了使用DFS,即从第一个字符开始,如果是0,那么有翻转或者不翻转两种可能,再往下搜索时判定上一位是0还是1,如果是0那么这一位可以翻转可以不翻转,如果是1,那么这一位就只能翻转。
这样DFS而不考虑剪枝的话是TLE的。后来想了一下,全0或者全1的情况排除,只剩下一种情况:以i点为轴,左边全为0,右边全为1。这样在极限的情况下就是全0或者全1的情况。那么可以这样考虑:以i为轴,i左边所有的数1翻转为0,右边的数0翻转成1。这样在代码上,可以先遍历一次字符串,统计0或者1的总数,第二次遍历,建立一个数组,储存该点左边有几个0或者1。第三次遍历,根据上面获得的变量利用数学推导(解一元方程而已)计算出来翻转次数。这样在O(n)的时间复杂度上解决该问题。
Java 代码
class Solution {
public static int Min(int a,int b){
return a > b ? b : a;
}
public int minFlipsMonoIncr(String S) {
int len = S.length();
int num0 = 0;
int[] left0 = new int[len];
for(int i = 0;i < len;i++){
if(S.charAt(i) == '0'){
num0++;
}
}
if(S.charAt(0) == '0'){
left0[0] = 1;
}else{
left0[0] = 0;
}
for(int i = 1;i < len;i++){
left0[i] = left0[i-1];
if(S.charAt(i) == '0'){
left0[i]++;
}
}
int ans = Min(num0,(len - num0));
for(int i = 0;i < len;i++){
int now = i+1+num0-2*left0[i];
ans = Min(ans,now);
}
return ans;
}
}