找到要翻转的零,以使连续 1 的数量最大化
给定一个二进制数组和一个整数 m,找到零翻转的位置,这会在数组中创建最大数量的连续 1。
例子 :
Input: arr[] = {1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1}
m = 2
Output: 5 7
We are allowed to flip maximum 2 zeroes. If we flip
arr[5] and arr[7], we get 8 consecutive 1's which is
maximum possible under given constraints
Input: arr[] = {1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1}
m = 1
Output: 7
We are allowed to flip maximum 1 zero. If we flip
arr[7], we get 5 consecutive 1's which is maximum
possible under given constraints.
Input: arr[] = {0, 0, 0, 1}
m = 4
Output: 0 1 2
Since m is more than number of zeroes, we can flip
all zeroes.
来源:http://www.careercup.com/question?id=5106425965576192
一个简单的解决方案是通过运行两个循环来考虑每个子数组。对于每个子数组,计算其中的零个数。返回具有 m 个或更少零的最大大小子数组。该解决方案的时间复杂度为 O(n 2 )。
更好的解决方案是使用辅助空间在 O(n) 时间内解决问题。
对于 0 的所有位置,计算 left[] 和 right[] 分别定义 i 左侧和 i 右侧连续 1 的数量。
例如,对于 arr[] = {1, 1, 0, 1, 1, 0, 0, 1, 1, 1} 和 m = 1,left[2] = 2 和 right[2] = 2,left[ 5] = 2,右[5] = 0,左[6] = 0,右[6] = 3。
left[] 和 right[] 可以通过遍历数组一次并跟踪最后一次看到的 1 和最后一次看到的 0 来填充 O(n) 时间。在填充 left[] 和 right[] 的同时,我们还将全零的索引存储在第三个数组说 zeroes[]。对于上面的例子,第三个数组存储 {2, 5, 6}
现在遍历 zeroes[] 并且对于这个数组中所有连续的 m 条目,计算可以产生的 1 的总和。这一步可以使用 left[] 和 right[] 在 O(n) 中完成。
C++
// C++ program to find positions of zeroes flipping which
// produces maximum number of consecutive 1's
#include
using namespace std;
// m is maximum of number zeroes allowed to flip
// n is size of array
vector maximized_one(int arr[], int n, int m)
{
// Left array
int left[n] = { 0 };
// Right array
int right[n] = { 0 };
// Array will contain zeroes position
vector zero_pos;
// Stores count
int count = 0;
int previous_index_of_zero = -1;
for (int i = 0; i < n; i++) {
if (arr[i]) {
count++;
}
else {
left[i] = count;
zero_pos.push_back(i);
if (previous_index_of_zero != i
&& previous_index_of_zero != -1) {
right[previous_index_of_zero] = count;
}
count = 0;
// To keep track of the previous index of zeroes
previous_index_of_zero = i;
}
}
right[previous_index_of_zero] = count;
int max_one = -1;
vector result_index;
int i = 0;
while (i <= (zero_pos.size()) - m) {
int temp = 0;
vector index;
for (int c = 0; c < m; c++) {
temp += left[zero_pos[i + c]]
+ right[zero_pos[i + c]] + 1;
// Index is updated
index.push_back(zero_pos[i + c]);
}
// Decrement temp by m-1 because when we are
// calculating temp we are adding 1 in it. So, in
// order to get exact count of 1. This decrement is
// applicable only when value of m is greater than 1
temp = temp - (m - 1);
// Updating max value when we get the new max temp
// and result_index as well
if (temp > max_one) {
max_one = temp;
result_index = index;
}
i += 1;
}
return result_index;
}
// Driver program
int main()
{
int arr[] = { 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1 };
int m = 2;
int n = sizeof(arr) / sizeof(arr[0]);
cout << "Index of zeroes that are flipped: ";
vector result_index = maximized_one(arr, n, m);
for (auto i : result_index) {
cout << i << " ";
}
return 0;
}
Java
// Java program to find positions of zeroes flipping which
// produces maximum number of consecutive 1's
import java.util.*;
class GFG{
// m is maximum of number zeroes allowed to flip
// n is size of array
static Vector maximized_one(int arr[], int n, int m)
{
// Left array
int left[] = new int[n];
// Right array
int right[] = new int[n];
// Array will contain zeroes position
Vector zero_pos = new Vector<>();
// Stores count
int count = 0;
int previous_index_of_zero = -1;
for (int i = 0; i < n; i++) {
if (arr[i]!=0) {
count++;
}
else {
left[i] = count;
zero_pos.add(i);
if (previous_index_of_zero != i
&& previous_index_of_zero != -1) {
right[previous_index_of_zero] = count;
}
count = 0;
// To keep track of the previous index of zeroes
previous_index_of_zero = i;
}
}
right[previous_index_of_zero] = count;
int max_one = -1;
Vector result_index = new Vector<>();
int i = 0;
while (i <= (zero_pos.size()) - m) {
int temp = 0;
Vector index = new Vector<>();
for (int c = 0; c < m; c++) {
temp += left[zero_pos.elementAt(i + c)]
+ right[zero_pos.elementAt(i + c)] + 1;
// Index is updated
index.add(zero_pos.elementAt(i + c));
}
// Decrement temp by m-1 because when we are
// calculating temp we are adding 1 in it. So, in
// order to get exact count of 1. This decrement is
// applicable only when value of m is greater than 1
temp = temp - (m - 1);
// Updating max value when we get the new max temp
// and result_index as well
if (temp > max_one) {
max_one = temp;
result_index = index;
}
i += 1;
}
return result_index;
}
// Driver program
public static void main(String[] args)
{
int arr[] = { 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1 };
int m = 2;
int n = arr.length;
System.out.print("Index of zeroes that are flipped: [");
Vector result_index = maximized_one(arr, n, m);
for (int i : result_index) {
System.out.print(i+ " ");
}
System.out.print("]");
}
}
// This code contributed by umadevi9616
Python3
# Python3 code for the above approach
def maximized_one(arr,n,m):
# Left array
left = [0]*n
# Right array
right = [0]*n
# Array will contain zeroes position
zero_pos = []
# Stores count
count = 0
previous_index_of_zero = -1
for i in range(n):
if arr[i] == 1:
count+=1
if arr[i] == 0:
left[i] = count
zero_pos.append(i)
if previous_index_of_zero !=i and previous_index_of_zero!=-1:
right[previous_index_of_zero] = count
count = 0
# To keep track of the previous index of zeroes
previous_index_of_zero = i
right[previous_index_of_zero] = count
# print(left)
# print(right)
# print(zero_pos)
max_one = -1
result_index = 0
i=0
while(i<=len(zero_pos)-m):
temp = 0
index = []
for c in range(m):
# print(zero_pos[i+c],left[zero_pos[i+c]],right[zero_pos[i+c]])
temp += left[zero_pos[i+c]] + right[zero_pos[i+c]] +1
# Index is updated
index.append(zero_pos[i+c])
# Decrement temp by m-1 because when we are calculating temp
# we are adding 1 in it.
# So, in order to get exact count of 1.
# This decrement is applicable only when value of m is greater than 1
temp = temp-(m-1)
# Updating max value when we get the new max temp
# and result_index as well
if temp > max_one:
max_one = temp
result_index = index
i+=1
return result_index
# Driver Code
if __name__ == '__main__':
arr = [1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1]
n = len(arr)
m = 2
print('Index of zeroes that are flipped: ',maximized_one(arr,n,m))
C#
// C# program to find positions of zeroes flipping which
// produces maximum number of consecutive 1's
using System;
using System.Collections.Generic;
public class GFG
{
// m is maximum of number zeroes allowed to flip
// n is size of array
static List maximized_one(int []arr, int n, int m)
{
// Left array
int []left = new int[n];
// Right array
int []right = new int[n];
// Array will contain zeroes position
List zero_pos = new List();
// Stores count
int count = 0;
int previous_index_of_zero = -1;
for (int j = 0; j < n; j++) {
if (arr[j] != 0) {
count++;
}
else {
left[j] = count;
zero_pos.Add(j);
if (previous_index_of_zero != j
&& previous_index_of_zero != -1) {
right[previous_index_of_zero] = count;
}
count = 0;
// To keep track of the previous index of zeroes
previous_index_of_zero = j;
}
}
right[previous_index_of_zero] = count;
int max_one = -1;
List result_index = new List();
int i = 0;
while (i <= (zero_pos.Count) - m) {
int temp = 0;
List index = new List();
for (int c = 0; c < m; c++) {
temp += left[zero_pos[i + c]]
+ right[zero_pos[i + c]] + 1;
// Index is updated
index.Add(zero_pos[i + c]);
}
// Decrement temp by m-1 because when we are
// calculating temp we are adding 1 in it. So, in
// order to get exact count of 1. This decrement is
// applicable only when value of m is greater than 1
temp = temp - (m - 1);
// Updating max value when we get the new max temp
// and result_index as well
if (temp > max_one) {
max_one = temp;
result_index = index;
}
i += 1;
}
return result_index;
}
// Driver program
public static void Main(String[] args)
{
int []arr = { 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1 };
int m = 2;
int n = arr.Length;
Console.Write("Index of zeroes that are flipped: [");
List result_index = maximized_one(arr, n, m);
foreach (int i in result_index) {
Console.Write(i+ " ");
}
Console.Write("]");
}
}
// This code is contributed by umadevi9616
Javascript
C++
// C++ program to find positions of zeroes flipping which
// produces maximum number of consecutive 1's
#include
using namespace std;
// m is maximum of number zeroes allowed to flip
// n is size of array
void findZeroes(int arr[], int n, int m)
{
// Left and right indexes of current window
int wL = 0, wR = 0;
// Left index and size of the widest window
int bestL = 0, bestWindow = 0;
// Count of zeroes in current window
int zeroCount = 0;
// While right boundary of current window doesn't cross
// right end
while (wR < n)
{
// If zero count of current window is less than m,
// widen the window toward right
if (zeroCount <= m)
{
if (arr[wR] == 0)
zeroCount++;
wR++;
}
// If zero count of current window is more than m,
// reduce the window from left
if (zeroCount > m)
{
if (arr[wL] == 0)
zeroCount--;
wL++;
}
// Update widest window if this window size is more
if ((wR-wL > bestWindow) && (zeroCount<=m))
{
bestWindow = wR-wL;
bestL = wL;
}
}
// Print positions of zeroes in the widest window
for (int i=0; i
Java
//Java to find positions of zeroes flipping which
// produces maximum number of consecutive 1's
class Test
{
static int arr[] = new int[]{1, 0, 0, 1, 1, 0, 1, 0, 1, 1};
// m is maximum of number zeroes allowed to flip
static void findZeroes(int m)
{
// Left and right indexes of current window
int wL = 0, wR = 0;
// Left index and size of the widest window
int bestL = 0, bestWindow = 0;
// Count of zeroes in current window
int zeroCount = 0;
// While right boundary of current window doesn't cross
// right end
while (wR < arr.length)
{
// If zero count of current window is less than m,
// widen the window toward right
if (zeroCount <= m)
{
if (arr[wR] == 0)
zeroCount++;
wR++;
}
// If zero count of current window is more than m,
// reduce the window from left
if (zeroCount > m)
{
if (arr[wL] == 0)
zeroCount--;
wL++;
}
// Update widest window if this window size is more
if ((wR-wL > bestWindow) && (zeroCount<=m))
{
bestWindow = wR-wL;
bestL = wL;
}
}
// Print positions of zeroes in the widest window
for (int i=0; i
Python3
# Python3 program to find positions
# of zeroes flipping which produces
# maximum number of consecutive 1's
# m is maximum of number zeroes allowed
# to flip, n is size of array
def findZeroes(arr, n, m) :
# Left and right indexes of current window
wL = wR = 0
# Left index and size of the widest window
bestL = bestWindow = 0
# Count of zeroes in current window
zeroCount = 0
# While right boundary of current
# window doesn't cross right end
while wR < n:
# If zero count of current window is less than m,
# widen the window toward right
if zeroCount <= m :
if arr[wR] == 0 :
zeroCount += 1
wR += 1
# If zero count of current window is more than m,
# reduce the window from left
if zeroCount > m :
if arr[wL] == 0 :
zeroCount -= 1
wL += 1
# Update widest window if
# this window size is more
if (wR-wL > bestWindow) and (zeroCount<=m) :
bestWindow = wR - wL
bestL = wL
# Print positions of zeroes
# in the widest window
for i in range(0, bestWindow):
if arr[bestL + i] == 0:
print (bestL + i, end = " ")
# Driver program
arr = [1, 0, 0, 1, 1, 0, 1, 0, 1, 1]
m = 2
n = len(arr)
print ("Indexes of zeroes to be flipped are", end = " ")
findZeroes(arr, n, m)
# This code is contributed by Shreyanshi Arun.
C#
// C# to find positions of zeroes flipping which
// produces maximum number of consecutive 1's
using System;
class Test
{
static int []arr = new int[]{1, 0, 0, 1, 1,
0, 1, 0, 1, 1};
// m is maximum of number zeroes allowed to flip
static void findZeroes(int m)
{
// Left and right indexes of current window
int wL = 0, wR = 0;
// Left index and size of the widest window
int bestL = 0, bestWindow = 0;
// Count of zeroes in current window
int zeroCount = 0;
// While right boundary of current
// window doesn't cross right end
while (wR < arr.Length)
{
// If zero count of current window is less
// than m, widen the window toward right
if (zeroCount <= m)
{
if (arr[wR] == 0)
zeroCount++;
wR++;
}
// If zero count of current window is more than m,
// reduce the window from left
if (zeroCount > m)
{
if (arr[wL] == 0)
zeroCount--;
wL++;
}
// Update widest window if this window size is more
if ((wR-wL > bestWindow) && (zeroCount<=m))
{
bestWindow = wR-wL;
bestL = wL;
}
}
// Print positions of zeroes in the widest window
for (int i = 0; i < bestWindow; i++)
{
if (arr[bestL + i] == 0)
Console.Write(bestL + i + " ");
}
}
// Driver method to test the above function
public static void Main(String[] args)
{
int m = 2;
Console.Write("Indexes of zeroes to be flipped are ");
findZeroes(m);
}
}
// This code is contributed by parashar
PHP
$m)
{
if ($arr[$wL] == 0)
$zeroCount--;
$wL++;
}
// Update widest window if
// this window size is more
if (($wR-$wL > $bestWindow) && ($zeroCount<=$m))
{
$bestWindow = $wR - $wL;
$bestL = $wL;
}
}
// Print positions of zeroes
// in the widest window
for($i = 0; $i < $bestWindow; $i++)
{
if ($arr[$bestL + $i] == 0)
echo $bestL + $i . " ";
}
}
// Driver Code
$arr = array(1, 0, 0, 1, 1, 0, 1, 0, 1, 1);
$m = 2;
$n = sizeof($arr)/sizeof($arr[0]);
echo "Indexes of zeroes to be flipped are ";
findZeroes($arr, $n, $m);
return 0;
// This code is contributed by nitin mittal.
?>
Javascript
Index of zeroes that are flipped: [5, 7]
一个有效的解决方案可以在 O(n) 时间和 O(1) 空间内解决问题。这个想法是为给定的数组使用滑动窗口。解决方案取自这里。
让我们使用从索引 wL 到索引 wR 的窗口覆盖。设窗口内的零个数为 zeroCount。我们维护里面最多有 m 个零的窗口。
主要步骤是:
– 当 zeroCount 不超过 m 时:向右扩展窗口 (wR++) 并更新计数 zeroCount。
– 当 zeroCount 超过 m 时,从左边缩小窗口(wL++),更新 zeroCount;
– 沿途更新最宽的窗口。输出零点的位置在最佳窗口内。
下面是这个想法的实现。
C++
// C++ program to find positions of zeroes flipping which
// produces maximum number of consecutive 1's
#include
using namespace std;
// m is maximum of number zeroes allowed to flip
// n is size of array
void findZeroes(int arr[], int n, int m)
{
// Left and right indexes of current window
int wL = 0, wR = 0;
// Left index and size of the widest window
int bestL = 0, bestWindow = 0;
// Count of zeroes in current window
int zeroCount = 0;
// While right boundary of current window doesn't cross
// right end
while (wR < n)
{
// If zero count of current window is less than m,
// widen the window toward right
if (zeroCount <= m)
{
if (arr[wR] == 0)
zeroCount++;
wR++;
}
// If zero count of current window is more than m,
// reduce the window from left
if (zeroCount > m)
{
if (arr[wL] == 0)
zeroCount--;
wL++;
}
// Update widest window if this window size is more
if ((wR-wL > bestWindow) && (zeroCount<=m))
{
bestWindow = wR-wL;
bestL = wL;
}
}
// Print positions of zeroes in the widest window
for (int i=0; i
Java
//Java to find positions of zeroes flipping which
// produces maximum number of consecutive 1's
class Test
{
static int arr[] = new int[]{1, 0, 0, 1, 1, 0, 1, 0, 1, 1};
// m is maximum of number zeroes allowed to flip
static void findZeroes(int m)
{
// Left and right indexes of current window
int wL = 0, wR = 0;
// Left index and size of the widest window
int bestL = 0, bestWindow = 0;
// Count of zeroes in current window
int zeroCount = 0;
// While right boundary of current window doesn't cross
// right end
while (wR < arr.length)
{
// If zero count of current window is less than m,
// widen the window toward right
if (zeroCount <= m)
{
if (arr[wR] == 0)
zeroCount++;
wR++;
}
// If zero count of current window is more than m,
// reduce the window from left
if (zeroCount > m)
{
if (arr[wL] == 0)
zeroCount--;
wL++;
}
// Update widest window if this window size is more
if ((wR-wL > bestWindow) && (zeroCount<=m))
{
bestWindow = wR-wL;
bestL = wL;
}
}
// Print positions of zeroes in the widest window
for (int i=0; i
Python3
# Python3 program to find positions
# of zeroes flipping which produces
# maximum number of consecutive 1's
# m is maximum of number zeroes allowed
# to flip, n is size of array
def findZeroes(arr, n, m) :
# Left and right indexes of current window
wL = wR = 0
# Left index and size of the widest window
bestL = bestWindow = 0
# Count of zeroes in current window
zeroCount = 0
# While right boundary of current
# window doesn't cross right end
while wR < n:
# If zero count of current window is less than m,
# widen the window toward right
if zeroCount <= m :
if arr[wR] == 0 :
zeroCount += 1
wR += 1
# If zero count of current window is more than m,
# reduce the window from left
if zeroCount > m :
if arr[wL] == 0 :
zeroCount -= 1
wL += 1
# Update widest window if
# this window size is more
if (wR-wL > bestWindow) and (zeroCount<=m) :
bestWindow = wR - wL
bestL = wL
# Print positions of zeroes
# in the widest window
for i in range(0, bestWindow):
if arr[bestL + i] == 0:
print (bestL + i, end = " ")
# Driver program
arr = [1, 0, 0, 1, 1, 0, 1, 0, 1, 1]
m = 2
n = len(arr)
print ("Indexes of zeroes to be flipped are", end = " ")
findZeroes(arr, n, m)
# This code is contributed by Shreyanshi Arun.
C#
// C# to find positions of zeroes flipping which
// produces maximum number of consecutive 1's
using System;
class Test
{
static int []arr = new int[]{1, 0, 0, 1, 1,
0, 1, 0, 1, 1};
// m is maximum of number zeroes allowed to flip
static void findZeroes(int m)
{
// Left and right indexes of current window
int wL = 0, wR = 0;
// Left index and size of the widest window
int bestL = 0, bestWindow = 0;
// Count of zeroes in current window
int zeroCount = 0;
// While right boundary of current
// window doesn't cross right end
while (wR < arr.Length)
{
// If zero count of current window is less
// than m, widen the window toward right
if (zeroCount <= m)
{
if (arr[wR] == 0)
zeroCount++;
wR++;
}
// If zero count of current window is more than m,
// reduce the window from left
if (zeroCount > m)
{
if (arr[wL] == 0)
zeroCount--;
wL++;
}
// Update widest window if this window size is more
if ((wR-wL > bestWindow) && (zeroCount<=m))
{
bestWindow = wR-wL;
bestL = wL;
}
}
// Print positions of zeroes in the widest window
for (int i = 0; i < bestWindow; i++)
{
if (arr[bestL + i] == 0)
Console.Write(bestL + i + " ");
}
}
// Driver method to test the above function
public static void Main(String[] args)
{
int m = 2;
Console.Write("Indexes of zeroes to be flipped are ");
findZeroes(m);
}
}
// This code is contributed by parashar
PHP
$m)
{
if ($arr[$wL] == 0)
$zeroCount--;
$wL++;
}
// Update widest window if
// this window size is more
if (($wR-$wL > $bestWindow) && ($zeroCount<=$m))
{
$bestWindow = $wR - $wL;
$bestL = $wL;
}
}
// Print positions of zeroes
// in the widest window
for($i = 0; $i < $bestWindow; $i++)
{
if ($arr[$bestL + $i] == 0)
echo $bestL + $i . " ";
}
}
// Driver Code
$arr = array(1, 0, 0, 1, 1, 0, 1, 0, 1, 1);
$m = 2;
$n = sizeof($arr)/sizeof($arr[0]);
echo "Indexes of zeroes to be flipped are ";
findZeroes($arr, $n, $m);
return 0;
// This code is contributed by nitin mittal.
?>
Javascript
Indexes of zeroes to be flipped are 5 7