输入一个只包含’0’和’1’的字符串,其中,‘0’可以翻转成’1’,‘1’可以翻转成’0’。请问至少需要翻转几个字符,才可以使翻转之后的字符串中所有的’0’位于’1’的前面?翻转之后的字符串可能只包含字符’0’或’1’。例如,输入字符串"00110",至少需要翻转一个字符才能使所有的’0’位于’1’的前面。可以将最后一个字符’0’翻转成’1’,得到字符串"00111"。
public class Test {
public static void main(String[] args) {
int result = minFlipsMonoIncr("00110");
System.out.println(result);
}
// f(i): 表示把字符串中S[0..i]变成符合要求的字符串并且最后一个字符是'0'所需要的最少翻转次数
// g(i): 表示把字符串中S[0..i]变成符合要求的字符串并且最后一个字符是'1'所需要的最少翻转次数
// f(i) = f(i-1) + ch == '0'?0:1
// g(i) = g(i-1) + Math.min(f(i-1),g(i-1)) + (ch == '1'?0:1);
public static int minFlipsMonoIncr(String S) {
int len = S.length();
if (len == 0) {
return 0;
}
// 第一个2:f(i)对应二维数组dp的第1行,g(i)对应dp的第2行
// 第二个2: 由于计算f(i)和g(i)只需要用到f(i-1)和g(i-1)的值
int[][] dp = new int[2][2];
char ch = S.charAt(0);
dp[0][0] = ch == '0' ? 0 : 1;
dp[1][0] = ch == '1' ? 0 : 1;
for (int i = 1; i < len; i++) {
ch = S.charAt(i);
int prev0 = dp[0][(i - 1) % 2];
int prev1 = dp[1][(i - 1) % 2];
dp[0][i % 2] = prev0 + (ch == '0' ? 0 : 1);
dp[1][i % 2] = Math.min(prev0, prev1) + (ch == '1' ? 0 : 1);
}
return Math.min(dp[0][(len - 1) % 2], dp[1][(len - 1) % 2]);
}
}