843. 数字翻转
给你一个01
构成的数组。请你找出最小翻转步数,使得数组满足以下规则:
1
的后面可以是1
或者0
,但是0
的后面必须是0
。
注意事项
- 输入的数组长度
n <= 100000
。
样例
给出 array = [1,0,0,1,1,1]
, 返回2
。
解释:
把两个0翻转成1。
给出 array = [1,0,1,0,1,0]
, 返回2
。
解释:
把第二个1和第三个1都翻转成0。
这题标签上写了动态规划,但感觉算不上。
对于长度为n的数组,只有n+1种反转后的状态,对于样例就是:
0,0,0,0,0,0
1,0,0,0,0,0
1,1,0,0,0,0
…..
1,1,1,1,1,1
因此可以先假设全翻转为0,记录1的个数t(需要1->0翻转的次数),然后从头开始遍历,使第i位之前都是1,第i位之后都是0。
具体操作就是遇到i=1时t-1(不需要翻转,但上面假设已经翻转过了,要再减回去),遇到i=0时t+1(多一次翻转),每次操作后更新t的最小值。
class Solution {
public:
/**
* @param nums: the array
* @return: the minimum times to flip digit
*/
int flipDigit(vector<int> &nums) {
// Write your code here
int t=0,min=INT32_MAX;
for(auto& i:nums)
{
if(i==1) t++;
}
for(auto& i:nums)
{
if(i==0) t++;
if(i==1) t--;
min=t<min?t:min;
}
return min;
}
};
但这些判断很耗时间,可以做一些优化,改完后运行时间快了四五倍。
class Solution {
public:
/**
* @param nums: the array
* @return: the minimum times to flip digit
*/
int flipDigit(vector<int> &nums) {
// Write your code here
int t=0,min=INT32_MAX;
for(auto& i:nums)
{
t+=i;
}
for(auto& i:nums)
{
t-=(i-0.5f)*2;
min=t<min?t:min;
}
return min;
}
};