您会得到N个不同的数字。您的任务是查找可以形成的2或3个组的数量,它们的总和可被3整除。
例子 :
Input : 1 5 7 2 9 14
Output : 13
The groups of two that can be
formed are:
(1, 5)
(5, 7)
(1, 2)
(2, 7)
(1, 14)
(7, 14)
The groups of three are:
(1, 5, 9)
(5, 7, 9)
(1, 2, 9)
(2, 7, 9)
(2, 5, 14)
(1, 9, 14)
(7, 9, 14)
Input : 3 6 9 12
Output : 10
All groups of 2 and 3 are valid.
天真的方法:对于每个数字,我们可以将其与其他每个数字相加,然后查看该总和是否可被3整除。然后存储这些总和,以便我们可以再次将每个数字相加,以检查是否有三个。
时间复杂度:2组为O(N ^ 2),3组为O(N ^ 3)
辅助空间:O(N ^ 2)
最佳方法
如果我们仔细查看每个数字,就会发现存在3种选择:
- 该数字可被3整除
- 该数字除以3的余数为1
- 该数字除以3的余数为2
现在,对于两个被3整除的组,这两个数字都必须属于类别1(两个都可以被3整除),或者一个数字应保留余数1,而另一个应保留余数2。这样,余数加起来到3,使总和被3整除。
要形成一个由三个组成的组,则所有三个数字应给出相同的余数,或者一个应给出余数0,另一个应给出1,最后一个应给出2。
这样,我们不在乎数字本身,而是在乎它们各自的余数。因此,通过将它们分为三类,我们可以使用一个简单的公式找到所有可能的组。
令C1为可被3整除的元素数。
令C2为剩余数为1的元素数。
令C3为剩余2的元素数。
Answer =
C2 * C3 + C1 * (C1 - 1) / 2 --> Groups of 2
+ C1 * (C1 - 1) * (C1 - 2) / 6
+ C2 * (C2 - 1) * (C2 - 2) / 6
+ C3 * (C3 - 1) * (C3 - 2) / 6 --> Groups of 3
with elements of same remainder
+ C1 * C2 * C3 --> Groups of three with all
distinct remainders
CPP
// Program to find groups of 2 or 3
// whose sum is divisible by 3
#include
using namespace std;
int numOfCombinations(int arr[], int N)
{
// Initialize groups to 0
int C[3] = { 0, 0, 0 };
// Increment group with specified remainder
for (int i = 0; i < N; ++i)
++C[arr[i] % 3];
// Return groups using the formula
return C[1] * C[2] + C[0] * (C[0] - 1) / 2 + C[0] * (C[0] - 1) * (C[0] - 2) / 6 + C[1] * (C[1] - 1) * (C[1] - 2) / 6 + C[2] * (C[2] - 1) * (C[2] - 2) / 6 + C[0] * C[1] * C[2];
}
// Driver Function
int main()
{
int arr1[6] = { 1, 5, 7, 2, 9, 14 };
cout << numOfCombinations(arr1, 6) << "\n";
int arr2[4] = { 3, 6, 9, 12 };
cout << numOfCombinations(arr2, 4) << "\n";
return 0;
}
Java
// Program to find groups of 2 or 3
// whose sum is divisible by 3
class GFG {
static int numOfCombinations(int arr[], int N)
{
// Initialize groups to 0
int C[] = { 0, 0, 0 };
// Increment group with specified remainder
for (int i = 0; i < N; ++i)
++C[arr[i] % 3];
// Return groups using the formula
return C[1] * C[2] + C[0] * (C[0] - 1) / 2 + C[0] * (C[0] - 1) * (C[0] - 2) / 6 + C[1] * (C[1] - 1) * (C[1] - 2) / 6 + C[2] * (C[2] - 1) * (C[2] - 2) / 6 + C[0] * C[1] * C[2];
}
// Driver code
public static void main(String[] args)
{
int arr1[] = { 1, 5, 7, 2, 9, 14 };
System.out.print(numOfCombinations(arr1, 6) + "\n");
int arr2[] = { 3, 6, 9, 12 };
System.out.print(numOfCombinations(arr2, 4) + "\n");
}
}
// This code is contributed by Anant Agarwal.
Python3
# Program to find groups of 2 or 3
# whose sum is divisible by 3
def numOfCombinations(arr, N):
# Initialize groups to 0
C = [0, 0, 0]
# Increment group with
# specified remainder
for i in range(N):
C[arr[i] % 3]= C[arr[i] % 3]+1
# Return groups using the formula
return (C[1] * C[2] + C[0] * (C[0] - 1) / 2 + C[0] * (C[0] - 1) * (C[0] - 2) / 6 + C[1] * (C[1] - 1) * (C[1] - 2) / 6 + C[2] * (C[2] - 1) * (C[2] - 2) / 6 + C[0] * C[1] * C[2])
# Driver code
arr1 = [1, 5, 7, 2, 9, 14]
print(int(numOfCombinations(arr1, 6)))
arr2 = [3, 6, 9, 12]
print(int(numOfCombinations(arr2, 4)))
# This code is contributed
# by Anant Agarwal.
C#
// C# Program to find groups of 2 or
// 3 whose sum is divisible by 3
using System;
class GFG {
// Function to find number of combinations
static int numOfCombinations(int[] arr,
int N)
{
// Initialize groups to 0
int[] C = { 0, 0, 0 };
// Increment group with specified remainder
for (int i = 0; i < N; ++i)
++C[arr[i] % 3];
// Return groups using the formula
return C[1] * C[2] + C[0] * (C[0] - 1) / 2 + C[0] * (C[0] - 1) * (C[0] - 2) / 6 + C[1] * (C[1] - 1) * (C[1] - 2) / 6 + C[2] * (C[2] - 1) * (C[2] - 2) / 6 + C[0] * C[1] * C[2];
}
// Driver code
public static void Main()
{
int[] arr1 = { 1, 5, 7, 2, 9, 14 };
Console.WriteLine(numOfCombinations(arr1, 6));
int[] arr2 = { 3, 6, 9, 12 };
Console.WriteLine(numOfCombinations(arr2, 4));
}
}
// This code is contributed by vt_m.
PHP
Javascript
输出 :
13
10