LintCode 843. 微软高频题:数字翻转
九章算法 - 帮助更多中国人找到好工作,硅谷顶尖IT企业工程师实时在线授课为你传授面试技巧www.jiuzhang.com描述
给定一个01
构成的数组。你可以翻转1
变成0
或者反转0
变成1
。
请问最少反转多少次可以使得数组满足以下规则:
1
的后面可以是1
或者0
,而0
的后面必须是0
。
样例
样例 1:
输入: [1,0,0,1,1,1]
输出: 2
解释: 把两个0翻转成1。
样例 2:
输入: [1,0,1,0,1,0]
输出: 2
解释: 把第二个1和第三个1都翻转成0。
题解
算法:dp
根据题给的0之后一定是0的条件,我们可以发现,最后通过翻转所形成的数组一定满足111111000000这样的形式,即在若干连续1之后出现若干个连续0(因为0后只能为0)。所以我们可以通过枚举10之间的分界点,依次算出它们的花费,取最小值。
- 开始统计出所有1的个数。
- 开始枚举分界点i,认为翻转完成后0~i都为1,i之后都为0
- 对于上述的数组,计算花费。
- 花费的内容由两部分构成:
- i之前为0的,需要转变为1。cost1=i-temp+1 0~i除了0都是1
- i之后为1的,需要转变为0。cost2=all-temp。即所有的1个数-0~i之间1的个数
- 对于所有的cost1+cost2 取最小值即可。
复杂度分析
- 时间复杂度
O(n)
- 枚举了数组的长度
- 空间复杂度
O(1)
- 消耗了常数的空间
/**
* This reference program is provided by @jiuzhang.com
* Copyright is reserved. Please indicate the source for forwarding
*/
public class Solution {
/**
* @param nums: the array
* @return: the minimum times to flip digit
*/
int min(int a, int b) {
if(a > b)
return b;
return a;
}
public int flipDigit(int[] nums) {
// Write your code here
int all = 0, temp = 0, ans;
for(int i = 0; i < nums.length; i++) {
if(nums[i] == 1) {
all++;
}
}
ans = all;
for(int i = 0; i < nums.length; i++) {
if(nums[i] == 1) {
temp++;
}
ans = min(ans, all - temp + i - temp + 1);
}
return ans;
}
}
// 九章动态规划专题班版本
public class Solution {
/**
* @param nums: the array
* @return: the minimum times to flip digit
*/
public int flipDigit(int[] A) {
int n = A.length;
if (n <= 1) {
return 0;
}
int[][] f = new int[n + 1][2];
f[0][0] = f[0][1] = 0;
int i, j, k, t;
for (i = 1; i <= n; ++i) {
for (j = 0; j < 2; ++j) {
f[i][j] = Integer.MAX_VALUE;
t = 0;
if (j != A[i - 1]) {
++t;
}
for (k = 0; k < 2; ++k) {
if (k == 0 && j == 1) continue;
f[i][j] = Math.min(f[i - 1][k] + t, f[i][j]);
}
}
}
return Math.min(f[n][0],f[n][1]);
}
}
/**
* This reference program is provided by @jiuzhang.com
* Copyright is reserved. Please indicate the source for forwarding
*/
public class Solution {
/**
* @param nums: the array
* @return: the minimum times to flip digit
*/
public int flipDigit(int[] A) {
//以0、1结尾的前i个数的最少翻转次数
int n = A.length;
int[] zero = new int[n + 1];
int[] one = new int[n + 1];
//初始化
zero[0] = one[0] = 0;
int i;
for (i = 1; i <= n; i++) {
zero[i] = A[i - 1] == 0 ? Math.min(one[i - 1], zero[i - 1]) :
Math.min(one[i - 1], zero[i - 1]) + 1;
one[i] = A[i - 1] == 1 ? one[i - 1] : one[i - 1] + 1;
}
return Math.min(zero[n], one[n]);
}
}
更多大厂高频考题,请点击LintCode进行在线评测