将二进制数组分成三个相等的具有相同值的部分
给定一个长度为 n 的数组 A,它只包含“ 0 s”和“ 1 s”。任务是将数组分成三个不同的非空部分,以便所有这些部分表示相同的二进制值(十进制)。
如果可能,返回任何 i+1 < j 的 [i, j],这样:
1. A[0], A[1], ..., A[i] 是第一部分。
2. A[i+1], A[i+2], ..., A[j-1] 是第二部分。
3. A[j], A[j+1], ..., A[n-1] 是第三部分。
注意:所有三个部分应具有相同的二进制值。但是,如果不可能,则返回 [-1, -1]。
例子:
Input : A = [1, 1, 1, 1, 1, 1]
Output : [1, 4]
All three parts are,
A[0] to A[1] first part,
A[2] to A[3] second part,
A[4] to A[5] third part.
Input : A = [1, 0, 0, 1, 0, 1]
Output : [0, 4]
方法:
假设 A 中的总数为 S。由于每个部分都有相同数量的 1,因此所有部分都应该有 K = S / 3 个。
如果 S 不能被 3 i:e S % 3 != 0整除,则该任务是不可能的。
现在我们将找到第 1 个、第 K 个、第 K+1 个、第 2K 个、第 2K+1 个和第 3K 个的位置。这些位置将形成 3 个区间: [i1, j1], [i2, j2], [i3, j3] 。 (如果只有 3 个,则间隔每个长度为 1。)
在间隔之间,可能有一些零。第三间隔 j3 之后的零必须包含在每个部分中:假设有 z 个(z = (S) - j3 的长度)。
所以第一部分[i1, j1]现在是[i1, j1+z] 。同样,第二部分[i2, j2]现在是[i2, j2+z] 。
如果这一切实际上都是可能的,那么最终的答案是[j1+z, j2+z+1] 。
下面是上述方法的实现。
C++
// C++ implementation of the
// above approach
#include
using namespace std;
// Function to return required
// interval answer.
vector ThreeEqualParts(vector A)
{
int imp[] = {-1, -1};
vector IMP(imp, imp + 2);
// Finding total number of ones
int Sum = accumulate(A.begin(),
A.end(), 0);
if (Sum % 3)
{
return IMP;
}
int K = Sum / 3;
// Array contains all zeros.
if (K == 0)
{
return {0, (int)A.size() - 1};
}
vector interval;
int S = 0;
for (int i = 0 ;i < A.size(); i++)
{
int x = A[i];
if (x)
{
S += x;
if (S == 1 or S == K + 1 or S == 2 * K + 1)
{
interval.push_back(i);
}
if (S == K or S == 2 * K or S == 3 * K)
{
interval.push_back(i);
}
}
}
int i1 = interval[0], j1 = interval[1],
i2 = interval[2], j2 = interval[3],
i3 = interval[4], j3 = interval[5];
vector a(A.begin() + i1, A.begin() + j1 + 1);
vector b(A.begin() + i2, A.begin() + j2 + 1);
vector c(A.begin() + i3, A.begin() + j3 + 1);
// The array is in the form
// W [i1, j1] X [i2, j2] Y [i3, j3] Z
// where [i1, j1] is a block of 1s, and so on.
if (!((a == b) and (b == c)))
{
return {-1, -1};
}
// x, y, z: the number of zeros
// after part 1, 2, 3
int x = i2 - j1 - 1;
int y = i3 - j2 - 1;
int z = A.size() - j3 - 1;
if (x < z or y < z)
{
return IMP;
}
// appending extra zeros at end of
// first and second interval
j1 += z;
j2 += z;
return {j1, j2 + 1};
}
// Driver Code
int main()
{
vector A = {1, 1, 1, 1, 1, 1};
// Output required result
vector res = ThreeEqualParts(A);
for(auto it :res)
cout << it << " ";
return 0;
}
// This code is contributed
// by Harshit Saini
Java
// Java implementation of the
// above approach
import java.util.*;
class GFG
{
// Function to return required
// interval answer.
public static int[] ThreeEqualParts(int[] A)
{
int IMP[] = new int[]{-1, -1};
// Finding total number of ones
int Sum = Arrays.stream(A).sum();
if ((Sum % 3) != 0)
{
return IMP;
}
int K = Sum / 3;
// Array contains all zeros.
if (K == 0)
{
return new int[]{0, A.length - 1};
}
ArrayList interval =
new ArrayList();
int S = 0;
for (int i = 0 ;i < A.length; i++)
{
int x = A[i];
if (x != 0)
{
S += x;
if ((S == 1) || (S == K + 1) ||
(S == 2 * K + 1))
{
interval.add(i);
}
if ((S == K) || (S == 2 * K) ||
(S == 3 * K))
{
interval.add(i);
}
}
}
int i1 = interval.get(0), j1 = interval.get(1),
i2 = interval.get(2), j2 = interval.get(3),
i3 = interval.get(4), j3 = interval.get(5);
int [] a = Arrays.copyOfRange(A, i1, j1 + 1);
int [] b = Arrays.copyOfRange(A, i2, j2 + 1);
int [] c = Arrays.copyOfRange(A, i3, j3 + 1);
// The array is in the form
// W [i1, j1] X [i2, j2] Y [i3, j3] Z
// where [i1, j1] is a block of 1s, and so on.
if (!(Arrays.equals(a, b) &&
Arrays.equals(b, c)))
{
return new int[]{-1, -1};
}
// x, y, z:
// the number of zeros after part 1, 2, 3
int x = i2 - j1 - 1;
int y = i3 - j2 - 1;
int z = A.length - j3 - 1;
if (x < z || y < z)
{
return IMP;
}
// appending extra zeros at end
// of first and second interval
j1 += z;
j2 += z;
return new int[]{j1, j2 + 1};
}
// Driver Code
public static void main(String []args)
{
int[] A = new int[]{1, 1, 1, 1, 1, 1};
// Output required result
int[] res = ThreeEqualParts(A);
System.out.println(Arrays.toString(res));
}
}
// This code is contributed
// by Harshit Saini
Python3
# Python implementation of the above approach
# Function to return required interval answer.
def ThreeEqualParts(A):
IMP = [-1, -1]
# Finding total number of ones
Sum = sum(A)
if Sum % 3:
return IMP
K = Sum / 3
# Array contains all zeros.
if K == 0:
return [0, len(A) - 1]
interval = []
S = 0
for i, x in enumerate(A):
if x:
S += x
if S in {1, K + 1, 2 * K + 1}:
interval.append(i)
if S in {K, 2 * K, 3 * K}:
interval.append(i)
i1, j1, i2, j2, i3, j3 = interval
# The array is in the form W [i1, j1] X [i2, j2] Y [i3, j3] Z
# where [i1, j1] is a block of 1s, and so on.
if not(A[i1:j1 + 1] == A[i2:j2 + 1] == A[i3:j3 + 1]):
return [-1, -1]
# x, y, z: the number of zeros after part 1, 2, 3
x = i2 - j1 - 1
y = i3 - j2 - 1
z = len(A) - j3 - 1
if x < z or y < z:
return IMP
# appending extra zeros at end of first and second interval
j1 += z
j2 += z
return [j1, j2 + 1]
# Driver Program
A = [1, 1, 1, 1, 1, 1]
# Output required result
print(ThreeEqualParts(A))
# This code is written by
# Sanjit_Prasad
C#
// C# implementation of the
// above approach
using System;
using System.Linq;
using System.Collections.Generic;
class GFG
{
// Function to return required
// interval answer.
static int[] ThreeEqualParts(int[] A)
{
int []IMP = new int[]{-1, -1};
// Finding total number of ones
int Sum = A.Sum();
if ((Sum % 3) != 0)
{
return IMP;
}
int K = Sum / 3;
// Array contains all zeros.
if (K == 0)
{
return new int[]{0, A.Length - 1};
}
List interval = new List();
int S = 0;
for (int i = 0 ;i < A.Length; i++)
{
int x = A[i];
if (x != 0)
{
S += x;
if ((S == 1) || (S == K + 1) ||
(S == 2 * K + 1))
{
interval.Add(i);
}
if ((S == K) || (S == 2 * K) ||
(S == 3 * K))
{
interval.Add(i);
}
}
}
int i1 = interval[0], j1 = interval[1],
i2 = interval[2], j2 = interval[3],
i3 = interval[4], j3 = interval[5];
var a = A.Skip(i1).Take(j1 - i1 + 1).ToArray();
var b = A.Skip(i2).Take(j2 - i2 + 1).ToArray();
var c = A.Skip(i3).Take(j3 - i3 + 1).ToArray();
// The array is in the form
// W [i1, j1] X [i2, j2] Y [i3, j3] Z
// where [i1, j1] is a block of 1s,
// and so on.
if (!(Enumerable.SequenceEqual(a,b) &&
Enumerable.SequenceEqual(b,c)))
{
return new int[]{-1, -1};
}
// x, y, z: the number of zeros
// after part 1, 2, 3
int X = i2 - j1 - 1;
int y = i3 - j2 - 1;
int z = A.Length - j3 - 1;
if (X < z || y < z)
{
return IMP;
}
// appending extra zeros at end
// of first and second interval
j1 += z;
j2 += z;
return new int[]{j1, j2 + 1};
}
// Driver Code
public static void Main()
{
int[] A = new int[]{1, 1, 1, 1, 1, 1};
// Output required result
int[] res = ThreeEqualParts(A);
Console.WriteLine(string.Join(" ", res));
}
}
// This code is contributed
// by Harshit Saini
PHP
$value)
{
echo $value." ";
}
// This code is contributed
// by Harshit Saini
?>
输出:
1 4
时间复杂度: O(N),其中 N 是 S 的长度。
空间复杂度: O(N)