0 和 1 数目相等的子数组
原文: https://www.geeksforgeeks.org/largest-subarray-with-equal-number-of-0s-and-1s/
给定一个仅包含 0 和 1 的数组,找到包含相等的 0 和 1 的最大子数组。 预期时间复杂度为O(n)
。
示例:
Input: arr[] = {1, 0, 1, 1, 1, 0, 0}
Output: 1 to 6
(Starting and Ending indexes of output subarray)
Input: arr[] = {1, 1, 1, 1}
Output: No such subarray
Input: arr[] = {0, 0, 1, 1, 0}
Output: 0 to 3 Or 1 to 4
方法 1:暴力。
方法:这些类型问题中的暴力方法是生成所有可能的子数组。 然后,首先检查子数组的 0 和 1 的数目是否相等。 为了简化此过程,将 0 作为 -1, 1 保持原样,对子数组分别累积总和。 累积总和等于 0 的点表示从开始到该点的子数组具有相等数量的 0 和 1。 现在,由于这是一个有效的子数组,请将其大小与迄今为止找到的此类子数组的最大大小进行比较。
算法:
-
使用起始指针表示子数组的起始点。
-
取一个变量
sum = 0
,它将取所有子数组元素的累加和。 -
如果起始点的值
= 1
则用 1 初始化,否则用 -1 初始化。 -
现在开始一个内部循环,并按照相同的逻辑开始累积元素的总和。
-
如果累积总和
= 0
,则表示子数组的 0 的数量等于 1。 -
现在,将其大小与最大子数组的大小进行比较,如果更大,则将此类子数组的第一个索引存储在变量中并更新大小的值。
-
打印具有上述算法返回的起始索引和大小的子数组。
伪代码:
Run a loop from i=0 to n-1
if(arr[i]==1)
sum=1
else
sum=-1
Run inner loop from j=i+1 to n-1
sum+=arr[j]
if(sum==0)
if(j-i+1>max_size)
start_index=i
max_size=j-i+1
Run a loop from i=start_index till max_size-1
print(arr[i])
C++
// A simple C++ program to find the largest
// subarray with equal number of 0s and 1s
#include <bits/stdc++.h>
using namespace std;
// This function Prints the starting and ending
// indexes of the largest subarray with equal
// number of 0s and 1s. Also returns the size
// of such subarray.
int findSubArray(int arr[], int n)
{
int sum = 0;
int maxsize = -1, startindex;
// Pick a starting point as i
for (int i = 0; i < n - 1; i++) {
sum = (arr[i] == 0) ? -1 : 1;
// Consider all subarrays starting from i
for (int j = i + 1; j < n; j++) {
(arr[j] == 0) ? (sum += -1) : (sum += 1);
// If this is a 0 sum subarray, then
// compare it with maximum size subarray
// calculated so far
if (sum == 0 && maxsize < j - i + 1) {
maxsize = j - i + 1;
startindex = i;
}
}
}
if (maxsize == -1)
cout << "No such subarray";
else
cout << startindex << " to "
<< startindex + maxsize - 1;
return maxsize;
}
/* Driver code*/
int main()
{
int arr[] = { 1, 0, 0, 1, 0, 1, 1 };
int size = sizeof(arr) / sizeof(arr[0]);
findSubArray(arr, size);
return 0;
}
// This code is contributed by rathbhupendra
C
// A simple program to find the largest subarray
// with equal number of 0s and 1s
#include <stdio.h>
// This function Prints the starting and ending
// indexes of the largest subarray with equal
// number of 0s and 1s. Also returns the size
// of such subarray.
int findSubArray(int arr[], int n)
{
int sum = 0;
int maxsize = -1, startindex;
// Pick a starting point as i
for (int i = 0; i < n - 1; i++) {
sum = (arr[i] == 0) ? -1 : 1;
// Consider all subarrays starting from i
for (int j = i + 1; j < n; j++) {
(arr[j] == 0) ? (sum += -1) : (sum += 1);
// If this is a 0 sum subarray, then
// compare it with maximum size subarray
// calculated so far
if (sum == 0 && maxsize < j - i + 1) {
maxsize = j - i + 1;
startindex = i;
}
}
}
if (maxsize == -1)
printf("No such subarray");
else
printf("%d to %d", startindex, startindex + maxsize - 1);
return maxsize;
}
/* Driver program to test above functions*/
int main()
{
int arr[] = { 1, 0, 0, 1, 0, 1, 1 };
int size = sizeof(arr) / sizeof(arr[0]);
findSubArray(arr, size);
return 0;
}
Java
class LargestSubArray {
// This function Prints the starting and ending
// indexes of the largest subarray with equal
// number of 0s and 1s. Also returns the size
// of such subarray.
int findSubArray(int arr[], int n)
{
int sum = 0;
int maxsize = -1, startindex = 0;
int endindex = 0;
// Pick a starting point as i
for (int i = 0; i < n - 1; i++) {
sum = (arr[i] == 0) ? -1 : 1;
// Consider all subarrays starting from i
for (int j = i + 1; j < n; j++) {
if (arr[j] == 0)
sum += -1;
else
sum += 1;
// If this is a 0 sum subarray, then
// compare it with maximum size subarray
// calculated so far
if (sum == 0 && maxsize < j - i + 1) {
maxsize = j - i + 1;
startindex = i;
}
}
}
endindex = startindex + maxsize - 1;
if (maxsize == -1)
System.out.println("No such subarray");
else
System.out.println(startindex + " to " + endindex);
return maxsize;
}
/* Driver program to test the above functions */
public static void main(String[] args)
{
LargestSubArray sub;
sub = new LargestSubArray();
int arr[] = { 1, 0, 0, 1, 0, 1, 1 };
int size = arr.length;
sub.findSubArray(arr, size);
}
}
Python3
# A simple program to find the largest subarray
# with equal number of 0s and 1s
# This function Prints the starting and ending
# indexes of the largest subarray with equal
# number of 0s and 1s. Also returns the size
# of such subarray.
def findSubArray(arr, n):
sum = 0
maxsize = -1
# Pick a starting point as i
for i in range(0, n-1):
sum = -1 if(arr[i] == 0) else 1
# Consider all subarrays starting from i
for j in range(i + 1, n):
sum = sum + (-1) if (arr[j] == 0) else sum + 1
# If this is a 0 sum subarray, then
# compare it with maximum size subarray
# calculated so far
if (sum == 0 and maxsize < j-i + 1):
maxsize = j - i + 1
startindex = i
if (maxsize == -1):
print("No such subarray");
else:
print(startindex, "to", startindex + maxsize-1);
return maxsize
# Driver program to test above functions
arr = [1, 0, 0, 1, 0, 1, 1]
size = len(arr)
findSubArray(arr, size)
# This code is contributed by Smitha Dinesh Semwal
C#
// A simple program to find the largest subarray
// with equal number of 0s and 1s
using System;
class GFG {
// This function Prints the starting and ending
// indexes of the largest subarray with equal
// number of 0s and 1s. Also returns the size
// of such subarray.
static int findSubArray(int[] arr, int n)
{
int sum = 0;
int maxsize = -1, startindex = 0;
int endindex = 0;
// Pick a starting point as i
for (int i = 0; i < n - 1; i++) {
sum = (arr[i] == 0) ? -1 : 1;
// Consider all subarrays starting from i
for (int j = i + 1; j < n; j++) {
if (arr[j] == 0)
sum += -1;
else
sum += 1;
// If this is a 0 sum subarray, then
// compare it with maximum size subarray
// calculated so far
if (sum == 0 && maxsize < j - i + 1) {
maxsize = j - i + 1;
startindex = i;
}
}
}
endindex = startindex + maxsize - 1;
if (maxsize == -1)
Console.WriteLine("No such subarray");
else
Console.WriteLine(startindex + " to " + endindex);
return maxsize;
}
// Driver program
public static void Main()
{
int[] arr = { 1, 0, 0, 1, 0, 1, 1 };
int size = arr.Length;
findSubArray(arr, size);
}
}
// This code is contributed by Sam007
PHP
<?php
// A simple program to find the
// largest subarray with equal
// number of 0s and 1s
// This function Prints the starting
// and ending indexes of the largest
// subarray with equal number of 0s
// and 1s. Also returns the size of
// such subarray.
function findSubArray(&$arr, $n)
{
$sum = 0;
$maxsize = -1;
// Pick a starting point as i
for ($i = 0; $i < $n - 1; $i++)
{
$sum = ($arr[$i] == 0) ? -1 : 1;
// Consider all subarrays
// starting from i
for ($j = $i + 1; $j < $n; $j++)
{
($arr[$j] == 0) ?
($sum += -1) : ($sum += 1);
// If this is a 0 sum subarray,
// then compare it with maximum
// size subarray calculated so far
if ($sum == 0 && $maxsize < $j - $i + 1)
{
$maxsize = $j - $i + 1;
$startindex = $i;
}
}
}
if ($maxsize == -1)
echo "No such subarray";
else
echo $startindex. " to " .
($startindex + $maxsize - 1);
return $maxsize;
}
// Driver Code
$arr = array(1, 0, 0, 1, 0, 1, 1);
$size = sizeof($arr);
findSubArray($arr, $size);
// This coed is contributed
// by ChitraNayal
?>
输出:
0 to 5
复杂度分析:
-
时间复杂度:
O(n ^ 2)
。由于所有可能的子数组都是使用一对嵌套循环生成的。
-
辅助空间:
O(1)
。因为没有使用占用辅助空间的额外数据结构。
方法 2:HashMap
。
方法:以 0 为 -1 的累积和概念将有助于我们优化该方法。 在求和时,有两种情况可以有一个子数组,其子数组的个数分别为 0 和 1。
-
当累积总和
= 0
时,表示从索引(0)到当前索引的子数组具有相等数量的 0 和 1。 -
当我们遇到之前已经遇到的累加总和值时,这意味着从先前索引加一到当前索引的子数组具有等于 0 和 1 的数量,他们给出的总和为 0。
简而言之,此问题等效于在array[]
中找到两个索引i & j
,使得array[i] = array[j]
和(j-i
)最大。 为了存储每个唯一累积总和值的第一次出现,我们使用hash_map
,如果再次获得该值,我们可以找到子数组的大小,并将其与迄今为止找到的最大大小进行比较。
算法:
-
令输入数组为大小为
n
的arr[]
,max_size
为输出子数组的大小。 -
创建大小为
n
的临时数组sumleft[]
。 将所有从arr[0]
到arr[i]
的元素的和存储在sumleft[i]
中。 -
有两种情况,输出子数组可能从第 0 个索引开始,也可能从其他索引开始。 我们将返回通过两种情况获得的最大值。
-
要找到从第 0 个索引开始的最大长度子数组,请扫描
sumleft[]
并在sumleft[i] = 0
的情况下找到最大i
。 -
现在,我们需要找到子数组
sum
等于 0 且起始索引不为 0 的子数组。此问题等效于在sumleft[]
中找到两个索引i & j
,使得sumleft[i] = sumleft[j]
和ji
最大。 为了解决这个问题,我们创建了一个大小为max-min + 1
的哈希表,其中min
是sumleft[]
中的最小值,而max
是sumleft[]
中的最大值。 将sumleft[]
中所有不同值的最左边出现的值散列。 哈希的大小选择为max-min + 1
,因为sumleft[]
中可能存在许多不同的可能值。 将哈希中的所有值初始化为 -1。 -
要填充并使用
hash[]
,请将sumleft[]
从 0 遍历到n-1
。 如果hash[]
中不存在值,则将其索引存储在hash
中。 如果存在该值,则计算sumleft[]
的当前索引与先前在hash[]
中存储的值的差。 如果此差异大于maxsize
,则更新maxsize
。 -
为了处理极端情况(全 1 和全 0),我们将
maxsize
初始化为 -1。 如果maxsize
保持为 -1,则打印不存在此类子数组。
伪代码:
int sum_left[n]
Run a loop from i=0 to n-1
if(arr[i]==0)
sumleft[i] = sumleft[i-1]+-1
else
sumleft[i] = sumleft[i-1]+-1
if (sumleft[i] max)
max = sumleft[i];
Run a loop from i=0 to n-1
if (sumleft[i] == 0)
{
maxsize = i+1;
startindex = 0;
}
// Case 2: fill hash table value. If already
then use it
if (hash[sumleft[i]-min] == -1)
hash[sumleft[i]-min] = i;
else
{
if ((i - hash[sumleft[i]-min]) > maxsize)
{
maxsize = i - hash[sumleft[i]-min];
startindex = hash[sumleft[i]-min] + 1;
}
}
return maxsize
C
// A O(n) program to find the largest subarray
// with equal number of 0s and 1s
#include <stdio.h>
#include <stdlib.h>
// A utility function to get maximum of two
// integers
int max(int a, int b) { return a > b ? a : b; }
// This function Prints the starting and ending
// indexes of the largest subarray with equal
// number of 0s and 1s. Also returns the size
// of such subarray.
int findSubArray(int arr[], int n)
{
// variables to store result values
int maxsize = -1, startindex;
// Create an auxiliary array sunmleft[].
// sumleft[i] will be sum of array
// elements from arr[0] to arr[i]
int sumleft[n];
// For min and max values in sumleft[]
int min, max;
int i;
// Fill sumleft array and get min and max
// values in it. Consider 0 values in arr[]
// as -1
sumleft[0] = ((arr[0] == 0) ? -1 : 1);
min = arr[0];
max = arr[0];
for (i = 1; i < n; i++) {
sumleft[i] = sumleft[i - 1]
+ ((arr[i] == 0) ? -1 : 1);
if (sumleft[i] < min)
min = sumleft[i];
if (sumleft[i] > max)
max = sumleft[i];
}
// Now calculate the max value of j - i such
// that sumleft[i] = sumleft[j]. The idea is
// to create a hash table to store indexes of all
// visited values.
// If you see a value again, that it is a case of
// sumleft[i] = sumleft[j]. Check if this j-i is
// more than maxsize.
// The optimum size of hash will be max-min+1 as
// these many different values of sumleft[i] are
// possible. Since we use optimum size, we need
// to shift all values in sumleft[] by min before
// using them as an index in hash[].
int hash[max - min + 1];
// Initialize hash table
for (i = 0; i < max - min + 1; i++)
hash[i] = -1;
for (i = 0; i < n; i++) {
// Case 1: when the subarray starts from
// index 0
if (sumleft[i] == 0) {
maxsize = i + 1;
startindex = 0;
}
// Case 2: fill hash table value. If already
// filled, then use it
if (hash[sumleft[i] - min] == -1)
hash[sumleft[i] - min] = i;
else {
if ((i - hash[sumleft[i] - min]) > maxsize) {
maxsize = i - hash[sumleft[i] - min];
startindex = hash[sumleft[i] - min] + 1;
}
}
}
if (maxsize == -1)
printf("No such subarray");
else
printf("%d to %d", startindex,
startindex + maxsize - 1);
return maxsize;
}
/* Driver program to test above functions */
int main()
{
int arr[] = { 1, 0, 0, 1, 0, 1, 1 };
int size = sizeof(arr) / sizeof(arr[0]);
findSubArray(arr, size);
return 0;
}
C++ / STL
// C++ program to find largest subarray with equal number of
// 0's and 1's.
#include <bits/stdc++.h>
using namespace std;
// Returns largest subarray with equal number of 0s and 1s
int maxLen(int arr[], int n)
{
// Creates an empty hashMap hM
unordered_map<int, int> hM;
int sum = 0; // Initialize sum of elements
int max_len = 0; // Initialize result
int ending_index = -1;
for (int i = 0; i < n; i++)
arr[i] = (arr[i] == 0) ? -1 : 1;
// Traverse through the given array
for (int i = 0; i < n; i++) {
// Add current element to sum
sum += arr[i];
// To handle sum=0 at last index
if (sum == 0) {
max_len = i + 1;
ending_index = i;
}
// If this sum is seen before, then update max_len
// if required
if (hM.find(sum + n) != hM.end()) {
if (max_len < i - hM[sum + n]) {
max_len = i - hM[sum + n];
ending_index = i;
}
}
else // Else put this sum in hash table
hM[sum + n] = i;
}
for (int i = 0; i < n; i++)
arr[i] = (arr[i] == -1) ? 0 : 1;
printf("%d to %d\n",
ending_index - max_len + 1, ending_index);
return max_len;
}
// Driver method
int main()
{
int arr[] = { 1, 0, 0, 1, 0, 1, 1 };
int n = sizeof(arr) / sizeof(arr[0]);
maxLen(arr, n);
return 0;
}
// This code is contributed by Aditya Goel
Java
import java.util.HashMap;
class LargestSubArray1 {
// Returns largest subarray with
// equal number of 0s and 1s
int maxLen(int arr[], int n)
{
// Creates an empty hashMap hM
HashMap<Integer, Integer> hM
= new HashMap<Integer, Integer>();
// Initialize sum of elements
int sum = 0;
// Initialize result
int max_len = 0;
int ending_index = -1;
int start_index = 0;
for (int i = 0; i < n; i++) {
arr[i] = (arr[i] == 0) ? -1 : 1;
}
// Traverse through the given array
for (int i = 0; i < n; i++) {
// Add current element to sum
sum += arr[i];
// To handle sum=0 at last index
if (sum == 0) {
max_len = i + 1;
ending_index = i;
}
// If this sum is seen before,
// then update max_len if required
if (hM.containsKey(sum + n)) {
if (max_len < i - hM.get(sum + n)) {
max_len = i - hM.get(sum + n);
ending_index = i;
}
}
else // Else put this sum in hash table
hM.put(sum + n, i);
}
for (int i = 0; i < n; i++) {
arr[i] = (arr[i] == -1) ? 0 : 1;
}
int end = ending_index - max_len + 1;
System.out.println(end + " to " + ending_index);
return max_len;
}
/* Driver program to test the above functions */
public static void main(String[] args)
{
LargestSubArray1 sub = new LargestSubArray1();
int arr[] = { 1, 0, 0, 1, 0, 1, 1 };
int n = arr.length;
sub.maxLen(arr, n);
}
}
// This code has been by Mayank Jaiswal(mayank_24)
Python3
# Python 3 program to find largest
# subarray with equal number of
# 0's and 1's.
# Returns largest subarray with
# equal number of 0s and 1s
def maxLen(arr, n):
# NOTE: Dictonary in python in
# implemented as Hash Maps.
# Create an empty hash map (dictionary)
hash_map = {}
curr_sum = 0
max_len = 0
ending_index = -1
for i in range (0, n):
if(arr[i] == 0):
arr[i] = -1
else:
arr[i] = 1
# Traverse through the given array
for i in range (0, n):
# Add current element to sum
curr_sum = curr_sum + arr[i]
# To handle sum = 0 at last index
if (curr_sum == 0):
max_len = i + 1
ending_index = i
# If this sum is seen before,
if curr_sum in hash_map:
# If max_len is smaller than new subarray
# Update max_len and ending_index
if max_len < i - hash_map[curr_sum]:
max_len = i - hash_map[curr_sum]
ending_index = i
else:
# else put this sum in dictionary
hash_map[curr_sum] = i
for i in range (0, n):
if(arr[i] == -1):
arr[i] = 0
else:
arr[i] = 1
print (ending_index - max_len + 1, end =" ")
print ("to", end = " ")
print (ending_index)
return max_len
# Driver Code
arr = [1, 0, 0, 1, 0, 1, 1]
n = len(arr)
maxLen(arr, n)
# This code is contributed
# by Tarun Garg
C
// C# program to find the largest subarray
// with equal number of 0s and 1s
using System;
using System.Collections.Generic;
class LargestSubArray1 {
// Returns largest subarray with
// equal number of 0s and 1s
public virtual int maxLen(int[] arr, int n)
{
// Creates an empty Dictionary hM
Dictionary<int,
int>
hM = new Dictionary<int,
int>();
int sum = 0; // Initialize sum of elements
int max_len = 0; // Initialize result
int ending_index = -1;
int start_index = 0;
for (int i = 0; i < n; i++) {
arr[i] = (arr[i] == 0) ? -1 : 1;
}
// Traverse through the given array
for (int i = 0; i < n; i++) {
// Add current element to sum
sum += arr[i];
// To handle sum=0 at last index
if (sum == 0) {
max_len = i + 1;
ending_index = i;
}
// If this sum is seen before,
// then update max_len
// if required
if (hM.ContainsKey(sum + n)) {
if (max_len < i - hM[sum + n]) {
max_len = i - hM[sum + n];
ending_index = i;
}
}
else // Else put this sum in hash table
{
hM[sum + n] = i;
}
}
for (int i = 0; i < n; i++) {
arr[i] = (arr[i] == -1) ? 0 : 1;
}
int end = ending_index - max_len + 1;
Console.WriteLine(end + " to " + ending_index);
return max_len;
}
// Driver Code
public static void Main(string[] args)
{
LargestSubArray1 sub = new LargestSubArray1();
int[] arr = new int[] {
1,
0,
0,
1,
0,
1,
1
};
int n = arr.Length;
sub.maxLen(arr, n);
}
}
// This code is contributed by Shrikant13
输出:
0 to 5
复杂度分析:
-
时间复杂度:
O(n)
。由于给定数组仅被遍历一次。
-
辅助空间:
O(n)
。由于使用了 hash_map ,因此需要额外的空间。
感谢 Aashish Barnwal 提出此解决方案。
版权属于:月萌API www.moonapi.com,转载请注明出处