📜  通过增加或减少K来最大化阵列的GCD

📅  最后修改于: 2021-04-17 15:43:15             🧑  作者: Mango

给定一个由N个正整数组成的数组arr [] 和一个正整数K ,任务是通过将任何数组元素增加或减少K来最大化数组arr []的GCD。

例子:

天真的方法:解决此问题的最简单方法是为每个数组元素arr [i]考虑所有三个选项,即,将arr [i]增加K ,将arr [i]减少K,或者既不增加也不减少arr [i ] 。使用递归生成在所有3种情况下形成的数组,并打印获得的所有数组的GCD最大值。

时间复杂度: O(3 N )
辅助空间: O(1)

高效方法:可以使用动态编程来优化上述方法。请按照以下步骤解决给定的问题:

  • 初始化一个辅助数组,例如dp [] [3] ,其中dp [i] [0]dp [i] [1]dp [i] [2]表示通过不更改直至i索引的最大GCD第i元素,分别将i元素增加或减少K。
  • 通过使用rr [0]rr [0] + Krr来更新dp [0] [0]dp [0] [1]dp [0] [2]来填充dp [] [3]的第一行[0] –K
  • 迭代范围[1,N – 1]并执行以下步骤:
    • 对于dp [i] [0] ,找到具有3个先前状态的A [i]的最大GCD,即dp [i – 1] [0],dp [i – 1] [1]dp [i – 1一次] [2] ,并将最大结果存储在dp [i] [0]中
    • 同样,通过分别取(arr [i] + K)(arr [i] – K)将结果存储在dp [i] [1]dp [i] [2]中
  • 完成上述步骤后,在结果dp [N – 1]行中打印最大值。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to return the maximum GCD
// by taking each operation
int findGCD(int x, int y, int z, int res)
{
    // Store the maximum GCD obtained
    // by either incrementing, decrementing
    // or not changing A[i]
    int ans = __gcd(x, res);
    ans = max(ans, __gcd(y, res));
    ans = max(ans, __gcd(z, res));
 
    // Return the maximum GCD
    return ans;
}
 
// Function to find the maximum GCD of
// the array arrA[] by either increasing
// or decreasing the array elements by K
int maximumGCD(int A[], int N, int K)
{
    // Initialize a dp table of size N*3
    int dp[N][3];
    memset(dp, 0, sizeof(dp));
 
    // Base Cases:
    // If only one element is present
    dp[0][0] = A[0];
    dp[0][1] = A[0] + K;
    dp[0][2] = A[0] - K;
 
    // Traverse the array A[] over indices [1, N - 1]
    for (int i = 1; i < N; i++) {
 
        // Store the previous state results
        int x = dp[i - 1][0];
        int y = dp[i - 1][1];
        int z = dp[i - 1][2];
 
        // Store maximum GCD result
        // for each current state
        dp[i][0] = findGCD(x, y, z, A[i]);
        dp[i][1] = findGCD(x, y, z, A[i] + K);
        dp[i][2] = findGCD(x, y, z, A[i] - K);
    }
 
    // Store the required result
    int mx = max(
        { 3, dp[N - 1][0], dp[N - 1][1],
          dp[N - 1][2] });
 
    // Return the result
    return mx;
}
 
// Driver Code
int main()
{
    int arr[] = { 3, 9, 15, 24 };
    int K = 1;
    int N = sizeof(arr) / sizeof(arr[0]);
 
    cout << maximumGCD(arr, N, K);
 
    return 0;
}


Java
// Java program for the above approach
import java.io.*;
import java.util.*;
class GFG
{
 
  // Recursive function to return gcd of a and b
  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 return the maximum GCD
  // by taking each operation
  static int findGCD(int x, int y, int z, int res)
  {
    // Store the maximum GCD obtained
    // by either incrementing, decrementing
    // or not changing A[i]
    int ans = gcd(x, res);
    ans = Math.max(ans, gcd(y, res));
    ans = Math.max(ans, gcd(z, res));
 
    // Return the maximum GCD
    return ans;
  }
 
  // Function to find the maximum GCD of
  // the array arrA[] by either increasing
  // or decreasing the array elements by K
  static int maximumGCD(int A[], int N, int K)
  {
    // Initialize a dp table of size N*3
    int dp[][] = new int[N][3];
    for (int i = 0; i < N; i++) {
      for (int j = 1; j < 3; j++) {
        dp[i][j] = 0;
      }
    }
 
    // Base Cases:
    // If only one element is present
    dp[0][0] = A[0];
    dp[0][1] = A[0] + K;
    dp[0][2] = A[0] - K;
 
    // Traverse the array A[] over indices [1, N - 1]
    for (int i = 1; i < N; i++) {
 
      // Store the previous state results
      int x = dp[i - 1][0];
      int y = dp[i - 1][1];
      int z = dp[i - 1][2];
 
      // Store maximum GCD result
      // for each current state
      dp[i][0] = findGCD(x, y, z, A[i]);
      dp[i][1] = findGCD(x, y, z, A[i] + K);
      dp[i][2] = findGCD(x, y, z, A[i] - K);
    }
 
    // Store the required result
    int mx = Math.max(3, Math.max(dp[N - 1][0], Math.max(dp[N - 1][1],
                                                         dp[N - 1][2])));
 
    // Return the result
    return mx;
  }
 
 
  // Driver code
  public static void main(String[] args)
  {
    int arr[] = { 3, 9, 15, 24 };
    int K = 1;
    int N = arr.length;
 
    System.out.print( maximumGCD(arr, N, K));
  }
}
 
// This code is contributed by sanjoy_62.


Python3
# Python3 program for the above approach
import math
 
# Function to return the maximum GCD
# by taking each operation
def findGCD(x, y, z, res):
     
    # Store the maximum GCD obtained
    # by either incrementing, decrementing
    # or not changing A[i]
    ans = math.gcd(x, res)
    ans = max(ans, math.gcd(y, res))
    ans = max(ans, math.gcd(z, res))
 
    # Return the maximum GCD
    return ans
 
# Function to find the maximum GCD of
# the array arrA[] by either increasing
# or decreasing the array elements by K
def maximumGCD(A, N, K):
     
    # Initialize a dp table of size N*3
    dp = [[0 for x in range(3)]
             for y in range(N)]
 
    # Base Cases:
    # If only one element is present
    dp[0][0] = A[0]
    dp[0][1] = A[0] + K
    dp[0][2] = A[0] - K
 
    # Traverse the array A[] over
    # indices [1, N - 1]
    for i in range(1, N):
         
        # Store the previous state results
        x = dp[i - 1][0]
        y = dp[i - 1][1]
        z = dp[i - 1][2]
 
        # Store maximum GCD result
        # for each current state
        dp[i][0] = findGCD(x, y, z, A[i])
        dp[i][1] = findGCD(x, y, z, A[i] + K)
        dp[i][2] = findGCD(x, y, z, A[i] - K)
 
    # Store the required result
    mx = max([3, dp[N - 1][0],
                 dp[N - 1][1],
                 dp[N - 1][2]])
 
    # Return the result
    return mx
 
# Driver Code
if __name__ == "__main__":
 
    arr = [ 3, 9, 15, 24 ]
    K = 1
    N = len(arr)
 
    print(maximumGCD(arr, N, K))
 
# This code is contributed by chitranayal


C#
// C# program to implement
// the above approach
using System;
class GFG
{
   
  // Recursive function to return gcd of a and b
  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 return the maximum GCD
  // by taking each operation
  static int findGCD(int x, int y, int z, int res)
  {
     
    // Store the maximum GCD obtained
    // by either incrementing, decrementing
    // or not changing A[i]
    int ans = gcd(x, res);
    ans = Math.Max(ans, gcd(y, res));
    ans = Math.Max(ans, gcd(z, res));
 
    // Return the maximum GCD
    return ans;
  }
 
  // Function to find the maximum GCD of
  // the array arrA[] by either increasing
  // or decreasing the array elements by K
  static int maximumGCD(int[] A, int N, int K)
  {
     
    // Initialize a dp table of size N*3
    int[,] dp = new int[N, 3];
    for (int i = 0; i < N; i++) {
      for (int j = 1; j < 3; j++) {
        dp[i, j] = 0;
      }
    }
 
    // Base Cases:
    // If only one element is present
    dp[0, 0] = A[0];
    dp[0, 1] = A[0] + K;
    dp[0, 2] = A[0] - K;
 
    // Traverse the array A[] over indices [1, N - 1]
    for (int i = 1; i < N; i++) {
 
      // Store the previous state results
      int x = dp[i - 1, 0];
      int y = dp[i - 1, 1];
      int z = dp[i - 1, 2];
 
      // Store maximum GCD result
      // for each current state
      dp[i, 0] = findGCD(x, y, z, A[i]);
      dp[i, 1] = findGCD(x, y, z, A[i] + K);
      dp[i, 2] = findGCD(x, y, z, A[i] - K);
    }
 
    // Store the required result
    int mx = Math.Max(3, Math.Max(dp[N - 1, 0], Math.Max(dp[N - 1, 1],
                                                         dp[N - 1, 2])));
 
    // Return the result
    return mx;
  }
 
  // Driver code
  public static void Main()
  {
    int[] arr = { 3, 9, 15, 24 };
    int K = 1;
    int N = arr.Length;
 
    Console.Write( maximumGCD(arr, N, K));
  }
}
 
// This code is contributed by susmitakundugoaldanga.


输出:
4

时间复杂度: O(N * log(M)),其中M数组arr []中最小元素
辅助空间: O(N)