Maximize GCD of an array by increments or decrements by K

• Last Updated : 06 May, 2021

Given an array arr[] consisting of N positive integers and a positive integer K, the task is to maximize the GCD of the array arr[] by either increasing or decreasing any array element by K.

Examples:

Input: arr[] = {3, 9, 15, 24}, K = 1
Output: 4
Explanation:
Perform the following operations on the array arr[]:
Increment arr by 1. Therefore, arr[] modifies to {4, 9, 15, 24}.
Decrement arr by 1. Therefore, arr[] modifies to {4, 8, 15, 24}.
Increment arr by 1. Therefore, arr[] modifies to {4, 8, 16, 24}.
Therefore, GCD of the modified array is 4.

Input: arr[] = {5, 9, 2}, K = 1
Output: 3

Naive Approach: The simplest approach to solve this problem is to consider all three options for each array element arr[i], i.e., increase arr[i] by K, decrease arr[i] by K or neither increment nor decrement arr[i]. Generate the arrays formed in all the 3 cases using recursion and print the maximum of GCD of all the arrays obtained.

Time Complexity: O(3N)
Auxiliary Space: O(1)

Efficient Approach: The above approach can be optimized using Dynamic Programming. Follow the steps below to solve the given problem:

• Initialize an auxiliary array, say dp[], where dp[i], dp[i], and dp[i] denotes the maximum GCD possible upto ith index by not changing the ith elements, incrementing or decrementing the ith element by K respectively.
• Fill the first row of dp[] by updating dp, dp and dp with arr, arr + K and arr – K respectively.
• Iterate over the range [1, N – 1] and perform the following steps:
• For dp[i], find the maximum GCD of A[i] with 3 previous states, i.e., dp[i – 1], dp[i – 1] and dp[i – 1] once at a time, and store the maximum result in dp[i].
• Similarly, store the results in dp[i] and dp[i] by taking (arr[i] + K) and (arr[i] – K) respectively.
• After completing the above steps, print the maximum value in the row dp[N – 1] as the result.

Below is the implementation of the above approach:

C++

 // C++ program for the above approach#include using namespace std; // Function to return the maximum GCD// by taking each operationint 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 Kint maximumGCD(int A[], int N, int K){    // Initialize a dp table of size N*3    int dp[N];    memset(dp, 0, sizeof(dp));     // Base Cases:    // If only one element is present    dp = A;    dp = A + K;    dp = A - 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];        int y = dp[i - 1];        int z = dp[i - 1];         // Store maximum GCD result        // for each current state        dp[i] = findGCD(x, y, z, A[i]);        dp[i] = findGCD(x, y, z, A[i] + K);        dp[i] = findGCD(x, y, z, A[i] - K);    }     // Store the required result    int mx = max(        { 3, dp[N - 1], dp[N - 1],          dp[N - 1] });     // Return the result    return mx;} // Driver Codeint main(){    int arr[] = { 3, 9, 15, 24 };    int K = 1;    int N = sizeof(arr) / sizeof(arr);     cout << maximumGCD(arr, N, K);     return 0;}

Java

 // Java program for the above approachimport 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];    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 = A;    dp = A + K;    dp = A - 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];      int y = dp[i - 1];      int z = dp[i - 1];       // Store maximum GCD result      // for each current state      dp[i] = findGCD(x, y, z, A[i]);      dp[i] = findGCD(x, y, z, A[i] + K);      dp[i] = findGCD(x, y, z, A[i] - K);    }     // Store the required result    int mx = Math.max(3, Math.max(dp[N - 1], Math.max(dp[N - 1],                                                         dp[N - 1])));     // 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 approachimport math # Function to return the maximum GCD# by taking each operationdef 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 Kdef 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 = A    dp = A + K    dp = A - 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]        y = dp[i - 1]        z = dp[i - 1]         # Store maximum GCD result        # for each current state        dp[i] = findGCD(x, y, z, A[i])        dp[i] = findGCD(x, y, z, A[i] + K)        dp[i] = findGCD(x, y, z, A[i] - K)     # Store the required result    mx = max([3, dp[N - 1],                 dp[N - 1],                 dp[N - 1]])     # Return the result    return mx # Driver Codeif __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 approachusing 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;    dp[0, 1] = A + K;    dp[0, 2] = A - 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.

Javascript


Output:
4

Time Complexity: O(N*log(M)), where M is the smallest element in the array arr[]
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up