给定一个大小为N的数组arr [] ,任务是计算将给定数组元素拆分为两个子数组的方式的数量,以使两个子数组的GCD相等。
例子:
Input: arr[] = {8, 4, 4, 8, 12}
Output: 2
Explanation:
Possible ways to split the array two groups of equal GCD are: { {{arr[0], arr[1]}, {arr[2], arr[3], arr[4]}}, {{arr[0], arr[1], arr[2]}, {arr[3], arr[4]}} }.
Therefore, the required output is 2.
Input: arr[] = {1, 2, 4, 6, 5}
Output: 2
天真的方法:解决此问题的最简单方法是遍历数组,并在每个数组索引处将数组划分为两个子数组,然后检查两个子数组的GCD是否相等。如果发现为真,则增加此类子数组的计数。最后,打印计数。
时间复杂度: O(N 2 )
辅助空间:O(N)
高效方法:为了优化上述方法,其思想是使用Prefix Sum Array技术。请按照以下步骤解决问题:
- 初始化一个变量,例如说cntWays,以存储将数组拆分为两个子数组的方式的数量,以使两个子数组的GCD相等。
- 初始化一个数组,例如prefixGCD []以存储数组元素的前缀GCD。
- 初始化一个数组,例如使用suffixGCD []存储数组元素的后缀GCD。
- 使用变量i遍历prefixGCD []和suffixGCD []数组,并检查prefixGCD [i]和suffixGCD [i + 1]是否相等。如果发现为真,则增加cntWays的值。
- 最后,打印cntWays的值。
下面是上述方法的实现:
C++
// C++ program to implement
// the above approach
#include
using namespace std;
// Function to count number of ways to split
// array into two groups with equal GCD value.
int cntWaysToSplitArrayTwo(int arr[], int N)
{
// Stores prefix GCD
// of the array
int prefixGCD[N];
// Update prefixGCD[0]
prefixGCD[0] = arr[0];
// Stores suffix GCD
// of the array
int suffixGCD[N];
// Update suffixGCD[N - 1]
suffixGCD[N - 1] = arr[N - 1];
// Traverse the array
for (int i = 1; i < N; i++) {
// Update prefixGCD[i]
prefixGCD[i]
= __gcd(prefixGCD[i - 1],
arr[i]);
}
// Traverse the array
for (int i = N - 2; i >= 0; i--) {
// Update prefixGCD[i]
suffixGCD[i]
= __gcd(suffixGCD[i + 1],
arr[i]);
}
// Stores count of ways to split array
// into two groups with equal GCD
int cntWays = 0;
// Traverse prefixGCD[] and suffixGCD[]
for (int i = 0; i < N - 1; i++) {
// If GCD of both groups equal
if (prefixGCD[i]
== suffixGCD[i + 1]) {
// Update cntWays
cntWays += 1;
}
}
return cntWays;
}
// Driver Code
int main()
{
int arr[] = { 8, 4, 4, 8, 12 };
int N = sizeof(arr) / sizeof(arr[0]);
cout << cntWaysToSplitArrayTwo(arr, N);
return 0;
}
Java
// Java program to implement
// the above approach
import java.io.*;
import java.util.*;
class GFG{
static int gcd(int a, int b)
{
// Everything divides 0
if (a == 0)
return b;
if (b == 0)
return a;
// Base case
if (a == b)
return a;
// a is greater
if (a > b)
return gcd(a - b, b);
return gcd(a, b - a);
}
// Function to count number of ways to split
// array into two groups with equal GCD value.
static int cntWaysToSplitArrayTwo(int arr[],
int N)
{
// Stores prefix GCD
// of the array
int prefixGCD[] = new int[N];
// Update prefixGCD[0]
prefixGCD[0] = arr[0];
// Stores suffix GCD
// of the array
int suffixGCD[] = new int[N];
// Update suffixGCD[N - 1]
suffixGCD[N - 1] = arr[N - 1];
// Traverse the array
for(int i = 1; i < N; i++)
{
// Update prefixGCD[i]
prefixGCD[i] = gcd(prefixGCD[i - 1],
arr[i]);
}
// Traverse the array
for(int i = N - 2; i >= 0; i--)
{
// Update prefixGCD[i]
suffixGCD[i] = gcd(suffixGCD[i + 1],
arr[i]);
}
// Stores count of ways to split array
// into two groups with equal GCD
int cntWays = 0;
// Traverse prefixGCD[] and suffixGCD[]
for(int i = 0; i < N - 1; i++)
{
// If GCD of both groups equal
if (prefixGCD[i] == suffixGCD[i + 1])
{
// Update cntWays
cntWays += 1;
}
}
return cntWays;
}
// Driver Code
public static void main(String[] args)
{
int arr[] = { 8, 4, 4, 8, 12 };
int N = arr.length;
System.out.print(cntWaysToSplitArrayTwo(arr, N));
}
}
// This code is contributed by sanjoy_62
Python3
# Python3 program to implement
# the above approach
import math
# Function to count number of ways to split
# array into two groups with equal GCD value.
def cntWaysToSplitArrayTwo(arr, N):
# Stores prefix GCD
# of the array
prefixGCD = [0] * N
# Update prefixGCD[0]
prefixGCD[0] = arr[0]
# Stores suffix GCD
# of the array
suffixGCD = [0] * N
# Update suffixGCD[N - 1]
suffixGCD[N - 1] = arr[N - 1]
# Traverse the array
for i in range(N):
# Update prefixGCD[i]
prefixGCD[i] = math.gcd(prefixGCD[i - 1], arr[i])
# Traverse the array
for i in range(N - 2, -1, -1):
# Update prefixGCD[i]
suffixGCD[i] = math.gcd(suffixGCD[i + 1], arr[i])
# Stores count of ways to split array
# into two groups with equal GCD
cntWays = 0
# Traverse prefixGCD[] and suffixGCD[]
for i in range(N - 1):
# If GCD of both groups equal
if (prefixGCD[i] == suffixGCD[i + 1]):
# Update cntWays
cntWays += 1
return cntWays
# Driver Code
arr = [ 8, 4, 4, 8, 12 ]
N = len(arr)
print(cntWaysToSplitArrayTwo(arr, N))
# This code is contributed by susmitakundugoaldanga
C#
// C# program to implement
// the above approach
using System;
class GFG{
static int gcd(int a, int b)
{
// Everything divides 0
if (a == 0)
return b;
if (b == 0)
return a;
// Base case
if (a == b)
return a;
// a is greater
if (a > b)
return gcd(a - b, b);
return gcd(a, b - a);
}
// Function to count number of ways to split
// array into two groups with equal GCD value.
static int cntWaysToSplitArrayTwo(int []arr,
int N)
{
// Stores prefix GCD
// of the array
int []prefixGCD = new int[N];
// Update prefixGCD[0]
prefixGCD[0] = arr[0];
// Stores suffix GCD
// of the array
int []suffixGCD = new int[N];
// Update suffixGCD[N - 1]
suffixGCD[N - 1] = arr[N - 1];
// Traverse the array
for(int i = 1; i < N; i++)
{
// Update prefixGCD[i]
prefixGCD[i] = gcd(prefixGCD[i - 1],
arr[i]);
}
// Traverse the array
for(int i = N - 2; i >= 0; i--)
{
// Update prefixGCD[i]
suffixGCD[i] = gcd(suffixGCD[i + 1],
arr[i]);
}
// Stores count of ways to split array
// into two groups with equal GCD
int cntWays = 0;
// Traverse prefixGCD[] and suffixGCD[]
for(int i = 0; i < N - 1; i++)
{
// If GCD of both groups equal
if (prefixGCD[i] == suffixGCD[i + 1])
{
// Update cntWays
cntWays += 1;
}
}
return cntWays;
}
// Driver Code
public static void Main(String[] args)
{
int []arr = { 8, 4, 4, 8, 12 };
int N = arr.Length;
Console.Write(cntWaysToSplitArrayTwo(arr, N));
}
}
// This code is contributed by Princi Singh
Javascript
输出:
2
时间复杂度: O(N)
辅助空间: O(N)