给定一个二进制数组,我们需要将该数组转换为一个包含全 1 或全 0 的数组。我们需要使用最少的组翻转次数来做到这一点。
例子 :
Input : arr[] = {1, 1, 0, 0, 0, 1}
Output : From 2 to 4
Explanation : We have two choices, we make all 0s or do all 1s. We need to do two group flips to make all elements 0 and one group flip to make all elements 1. Since making all elements 1 takes least group flips, we do this.
Input : arr[] = {1, 0, 0, 0, 1, 0, 0, 1, 0, 1}
Output :
From 1 to 3
From 5 to 6
From 8 to 8
Input : arr[] = {0, 0, 0}
Output :
Explanation : Output is empty, we need not to make any change
Input : arr[] = {1, 1, 1}
Output :
Explanation : Output is empty, we need not to make any change
Input : arr[] = {0, 1}
Output :
From 0 to 0
OR
From 1 to 1
Explanation : Here number of flips are same either we make all elements as 1 or all elements as 0.
一个朴素的解决方案是遍历数组的两次遍历。我们首先遍历找到0的组数和1的组数,我们找到这两者中的最小值。然后我们遍历数组并在 1 组较少时翻转 1。否则,我们翻转 0。
如何通过一次数组遍历来做到这一点?
一个有效的解决方案基于以下事实:
- 只有两种类型的组(0 组和 1 组)
- 要么两组的计数相同,要么计数之间的差值最多为1。例如,在{1, 1, 0, 1, 0, 0}中有两组0和两组1。例如{1, 1, 0, 0, 0, 1, 0, 0, 1, 1},1组的个数比0的个数多1。
基于以上事实,我们可以得出结论,如果我们总是翻转第二组和与第二组相同类型的其他组,我们总是得到正确的答案。在第一种情况下,当组数相同时,我们翻转哪种组类型并不重要,因为两者都会导致正确答案。在第二种情况下,当有多余的时候,通过忽略第一组并从第二组开始,我们将这种情况转换为第一种情况(对于从第二组开始的子数组)并得到正确答案。
C++
// C++ program to find the minimum
// group flips in a binary array
#include
using namespace std;
void printGroups(bool arr[], int n) {
// Traverse through all array elements
// starting from the second element
for (int i = 1; i < n; i++) {
// If current element is not same
// as previous
if (arr[i] != arr[i - 1]) {
// If it is same as first element
// then it is starting of the interval
// to be flipped.
if (arr[i] != arr[0])
cout << "From " << i << " to ";
// If it is not same as previous
// and same as first element, then
// previous element is end of interval
else
cout << (i - 1) << endl;
}
}
// Explicitly handling the end of
// last interval
if (arr[n - 1] != arr[0])
cout << (n - 1) << endl;
}
int main() {
bool arr[] = {0, 1, 1, 0, 0, 0, 1, 1};
int n = sizeof(arr) / sizeof(arr[0]);
printGroups(arr, n);
return 0;
}
Java
// Java program to find the minimum
// group flips in a binary array
import java.io.*;
import java.util.*;
class GFG {
static void printGroups(int arr[], int n)
{
// Traverse through all array elements
// starting from the second element
for(int i = 1; i < n; i++)
{
// If current element is not same
// as previous
if (arr[i] != arr[i - 1])
{
// If it is same as first element
// then it is starting of the interval
// to be flipped.
if (arr[i] != arr[0])
System.out.print("From " + i + " to ");
// If it is not same as previous
// and same as first element, then
// previous element is end of interval
else
System.out.println(i - 1);
}
}
// Explicitly handling the end of
// last interval
if (arr[n - 1] != arr[0])
System.out.println(n - 1);
}
// Driver code
public static void main(String[] args)
{
int arr[] = {0, 1, 1, 0, 0, 0, 1, 1};
int n = arr.length;
printGroups(arr, n);
}
}
// This code is contributed by coder001
Python3
# Python3 program to find the minimum
# group flips in a binary array
def printGroups(arr, n):
# Traverse through all array elements
# starting from the second element
for i in range(1, n):
# If current element is not same
# as previous
if (arr[i] != arr[i - 1]):
# If it is same as first element
# then it is starting of the interval
# to be flipped.
if (arr[i] != arr[0]):
print("From", i, "to ", end = "")
# If it is not same as previous
# and same as the first element, then
# previous element is end of interval
else:
print(i - 1)
# Explicitly handling the end of
# last interval
if (arr[n - 1] != arr[0]):
print(n - 1)
# Driver Code
if __name__ == '__main__':
arr = [ 0, 1, 1, 0, 0, 0, 1, 1 ]
n = len(arr)
printGroups(arr, n)
# This code is contributed by Bhupendra_Singh
C#
// C# program to find the minimum
// group flips in a binary array
using System;
class GFG{
static void printGroups(int []arr, int n)
{
// Traverse through all array elements
// starting from the second element
for(int i = 1; i < n; i++)
{
// If current element is not same
// as previous
if (arr[i] != arr[i - 1])
{
// If it is same as first element
// then it is starting of the interval
// to be flipped.
if (arr[i] != arr[0])
Console.Write("From " + i + " to ");
// If it is not same as previous
// and same as first element, then
// previous element is end of interval
else
Console.WriteLine(i - 1);
}
}
// Explicitly handling the end
// of last interval
if (arr[n - 1] != arr[0])
Console.WriteLine(n - 1);
}
// Driver code
public static void Main(String[] args)
{
int []arr = { 0, 1, 1, 0, 0, 0, 1, 1 };
int n = arr.Length;
printGroups(arr, n);
}
}
// This code is contributed by amal kumar choubey
Javascript
From 1 to 2
From 6 to 7
时间复杂度: O(n)
辅助空间: O(1)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live