Skip to content
Related Articles

Related Articles

Improve Article
Save Article
Like Article

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:

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

Input: arr[] = {3, 9, 15, 24}, K = 1
Output: 4
Explanation:
Perform the following operations on the array arr[]:
Increment arr[0] by 1. Therefore, arr[] modifies to {4, 9, 15, 24}.
Decrement arr[1] by 1. Therefore, arr[] modifies to {4, 8, 15, 24}.
Increment arr[2] 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[][3], where dp[i][0], dp[i][1], and dp[i][2] 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[][3] by updating dp[0][0], dp[0][1] and dp[0][2] with arr[0], arr[0] + K and arr[0] – K respectively.
  • Iterate over the range [1, N – 1] and perform the following steps:
    • For dp[i][0], find the maximum GCD of A[i] with 3 previous states, i.e., dp[i – 1][0], dp[i – 1][1] and dp[i – 1][2] once at a time, and store the maximum result in dp[i][0].
    • Similarly, store the results in dp[i][1] and dp[i][2] 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 <bits/stdc++.h>
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.

Javascript




<script>
//Javascript program for the above approach
 
function gcd( a, 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 findGCD(x, y, z,  res)
{
    // Store the maximum GCD obtained
    // by either incrementing, decrementing
    // or not changing A[i]
    var 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
function maximumGCD( A, N, K)
{
    // Initialize a dp table of size N*3
var dp = new Array(N).fill(0).map(() => new Array(3).fill(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 (var i = 1; i < N; i++) {
 
        // Store the previous state results
        var x = dp[i - 1][0];
        var y = dp[i - 1][1];
        var 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
    var 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;
}
 
var arr = [ 3, 9, 15, 24 ];
    var K = 1;
    var N = arr.length;
 
document.write( maximumGCD(arr, N, K));
 
 
//This code is contributed by SoumikMondal
</script>
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
Recommended Articles
Page :

Start Your Coding Journey Now!