# Smallest Subarray with given GCD

Given an array arr[] of n numbers and an integer k, find length of the minimum sub-array with gcd equals to k.

Example:

```Input: arr[] = {6, 9, 7, 10, 12,
24, 36, 27},
K = 3
Output: 2
Explanation: GCD of subarray {6,9} is 3.
GCD of subarray {24,36,27} is also 3,
but {6,9} is the smallest ```

Note: Time complexity analysis of below approaches assume that numbers are fixed size and finding GCD of two elements take constant time.

## Recommended: Please solve it on “PRACTICE” first, before moving on to the solution.

Method 1

Find GCD of all subarrays and keep track of the minimum length subarray with gcd k. Time Complexity of this is O(n3), O(n2) for each subarray and O(n) for finding gcd of a subarray.

Method 2

Find GCD of all subarrays using segment tree based approach discussed here. Time complexity of this solution is O(n2logn), O(n2) for each subarray and O(logn) for finding GCD of subarray using segment tree.

Method 3

The idea is to use Segment Tree and Binary Search to achieve time complexity O(n (logn)2).

1. If we have any number equal to ‘k’ in the array then the answer is 1 as GCD of k is k. Return 1.
2. If there is no number which is divisible by k, then GCD doesn’t exist. Return -1.
3. If none of the above cases is true, the length of minimum subarray is either greater than 1 or GCD doesn’t exist. In this case, we follow following steps.
• Build segment tree so that we can quicky find GCD of any subarray using the approach discussed here
• After building Segment Tree, we consider every index as starting point and do binary search for ending point such that the subarray between these two points has GCD k

Following is the implementation of above idea.

## C++

 `// C++ Program to find GCD of a number in a given Range ` `// using segment Trees ` `#include ` `using` `namespace` `std; ` ` `  `// To store segment tree ` `int` `*st; ` ` `  `// Function to find gcd of 2 numbers. ` `int` `gcd(``int` `a, ``int` `b) ` `{ ` `    ``if` `(a < b) ` `        ``swap(a, b); ` `    ``if` `(b==0) ` `        ``return` `a; ` `    ``return` `gcd(b, a%b); ` `} ` ` `  `/*  A recursive function to get gcd of given ` `    ``range of array indexes. The following are parameters for ` `    ``this function. ` ` `  `    ``st    --> Pointer to segment tree ` `    ``si --> Index of current node in the segment tree. Initially ` `               ``0 is passed as root is always at index 0 ` `    ``ss & se  --> Starting and ending indexes of the segment ` `                 ``represented by current node, i.e., st[index] ` `    ``qs & qe  --> Starting and ending indexes of query range */` `int` `findGcd(``int` `ss, ``int` `se, ``int` `qs, ``int` `qe, ``int` `si) ` `{ ` `    ``if` `(ss>qe || se < qs) ` `        ``return` `0; ` `    ``if` `(qs<=ss && qe>=se) ` `        ``return` `st[si]; ` `    ``int` `mid = ss+(se-ss)/2; ` `    ``return` `gcd(findGcd(ss, mid, qs, qe, si*2+1), ` `               ``findGcd(mid+1, se, qs, qe, si*2+2)); ` `} ` ` `  `//Finding The gcd of given Range ` `int` `findRangeGcd(``int` `ss, ``int` `se, ``int` `arr[], ``int` `n) ` `{ ` `    ``if` `(ss<0 || se > n-1 || ss>se) ` `    ``{ ` `        ``cout << ``"Invalid Arguments"` `<< ``"\n"``; ` `        ``return` `-1; ` `    ``} ` `    ``return` `findGcd(0, n-1, ss, se, 0); ` `} ` ` `  `// A recursive function that constructs Segment Tree for ` `// array[ss..se]. si is index of current node in segment ` `// tree st ` `int` `constructST(``int` `arr[], ``int` `ss, ``int` `se, ``int` `si) ` `{ ` `    ``if` `(ss==se) ` `    ``{ ` `        ``st[si] = arr[ss]; ` `        ``return` `st[si]; ` `    ``} ` `    ``int` `mid = ss+(se-ss)/2; ` `    ``st[si] = gcd(constructST(arr, ss, mid, si*2+1), ` `                 ``constructST(arr, mid+1, se, si*2+2)); ` `    ``return` `st[si]; ` `} ` ` `  `/* Function to construct segment tree from given array. ` `   ``This function allocates memory for segment tree and ` `   ``calls constructSTUtil() to fill the allocated memory */` `int` `*constructSegmentTree(``int` `arr[], ``int` `n) ` `{ ` `    ``int` `height = (``int``)(``ceil``(log2(n))); ` `    ``int` `size = 2*(``int``)``pow``(2, height)-1; ` `    ``st = ``new` `int``[size]; ` `    ``constructST(arr, 0, n-1, 0); ` `    ``return` `st; ` `} ` ` `  `// Returns size of smallest subarray of arr[0..n-1] ` `// with GCD equal to k. ` `int` `findSmallestSubarr(``int` `arr[], ``int` `n, ``int` `k) ` `{ ` `    ``// To check if a multiple of k exists. ` `    ``bool` `found = ``false``; ` ` `  `    ``// Find if k or its multiple is present ` `    ``for` `(``int` `i=0; i k) ` `                ``low = mid; ` ` `  `            ``// If GCD is k, store this point and look for ` `            ``// a closer point ` `            ``else` `if` `(gcd == k) ` `            ``{ ` `                ``high = mid; ` `                ``closest = mid; ` `                ``break``; ` `            ``} ` ` `  `            ``// If GCD is less than, look closer ` `            ``else` `                ``high = mid; ` ` `  `            ``// If termination condition reached, set ` `            ``// closest ` `            ``if` `(``abs``(high-low) <= 1) ` `            ``{ ` `                ``if` `(findRangeGcd(i, low, arr, n) == k) ` `                    ``closest = low; ` `                ``else` `if` `(findRangeGcd(i, high, arr, n)==k) ` `                    ``closest = high; ` `                ``break``; ` `            ``} ` `        ``} ` ` `  `        ``if` `(closest != 0) ` `            ``res = min(res, closest - i + 1); ` `    ``} ` ` `  `    ``// If res was not changed by loop, return -1, ` `    ``// else return its value. ` `    ``return` `(res == n+1) ? -1 : res; ` `} ` ` `  `// Driver program to test above functions ` `int` `main() ` `{ ` `    ``int` `n = 8; ` `    ``int` `k = 3; ` `    ``int` `arr[] = {6, 9, 7, 10, 12, 24, 36, 27}; ` `    ``cout << ``"Size of smallest sub-array with given"` `         ``<< ``" size is "` `<< findSmallestSubarr(arr, n, k); ` `    ``return` `0; ` `} `

## Java

 `// Java Program to find GCD of a number in a given Range ` `// using segment Trees ` `class` `GFG  ` `{ ` ` `  `// To store segment tree ` `static` `int` `[]st; ` ` `  `// Function to find gcd of 2 numbers. ` `static` `int` `gcd(``int` `a, ``int` `b) ` `{ ` `    ``if` `(a < b) ` `        ``swap(a, b); ` `    ``if` `(b == ``0``) ` `        ``return` `a; ` `    ``return` `gcd(b, a % b); ` `} ` ` `  `private` `static` `void` `swap(``int` `x, ``int` `y)  ` `{ ` `    ``int` `temp = x; ` `    ``x = y; ` `    ``y = temp; ` `}  ` `/* A recursive function to get gcd of given ` `    ``range of array indexes. The following are parameters for ` `    ``this function. ` ` `  `    ``st --> Pointer to segment tree ` `    ``si --> Index of current node in the segment tree. Initially ` `            ``0 is passed as root is always at index 0 ` `    ``ss & se --> Starting and ending indexes of the segment ` `                ``represented by current node, i.e., st[index] ` `    ``qs & qe --> Starting and ending indexes of query range */` `static` `int` `findGcd(``int` `ss, ``int` `se, ``int` `qs, ``int` `qe, ``int` `si) ` `{ ` `    ``if` `(ss > qe || se < qs) ` `        ``return` `0``; ` `    ``if` `(qs <= ss && qe >= se) ` `        ``return` `st[si]; ` `    ``int` `mid = ss + (se - ss) / ``2``; ` `    ``return` `gcd(findGcd(ss, mid, qs, qe, si * ``2` `+ ``1``), ` `            ``findGcd(mid + ``1``, se, qs, qe, si * ``2` `+ ``2``)); ` `} ` ` `  `// Finding The gcd of given Range ` `static` `int` `findRangeGcd(``int` `ss, ``int` `se, ``int` `arr[], ``int` `n) ` `{ ` `    ``if` `(ss < ``0` `|| se > n-``1` `|| ss > se) ` `    ``{ ` `        ``System.out.println(``"Invalid Arguments"``); ` `        ``return` `-``1``; ` `    ``} ` `    ``return` `findGcd(``0``, n - ``1``, ss, se, ``0``); ` `} ` ` `  `// A recursive function that constructs Segment Tree for ` `// array[ss..se]. si is index of current node in segment ` `// tree st ` `static` `int` `constructST(``int` `arr[], ``int` `ss, ``int` `se, ``int` `si) ` `{ ` `    ``if` `(ss == se) ` `    ``{ ` `        ``st[si] = arr[ss]; ` `        ``return` `st[si]; ` `    ``} ` `    ``int` `mid = ss + (se - ss) / ``2``; ` `    ``st[si] = gcd(constructST(arr, ss, mid, si * ``2` `+ ``1``), ` `                ``constructST(arr, mid+``1``, se, si * ``2` `+ ``2``)); ` `    ``return` `st[si]; ` `} ` ` `  `/* Function to construct segment tree from given array. ` `This function allocates memory for segment tree and ` `calls constructSTUtil() to fill the allocated memory */` `static` `int` `[]constructSegmentTree(``int` `arr[], ``int` `n) ` `{ ` `    ``int` `height = (``int``)(Math.ceil(Math.log(n))); ` `    ``int` `size = ``2``*(``int``)Math.pow(``2``, height) - ``1``; ` `    ``st = ``new` `int``[size]; ` `    ``constructST(arr, ``0``, n - ``1``, ``0``); ` `    ``return` `st; ` `} ` ` `  `// Returns size of smallest subarray of arr[0..n-1] ` `// with GCD equal to k. ` `static` `int` `findSmallestSubarr(``int` `arr[], ``int` `n, ``int` `k) ` `{ ` `    ``// To check if a multiple of k exists. ` `    ``boolean` `found = ``false``; ` ` `  `    ``// Find if k or its multiple is present ` `    ``for` `(``int` `i = ``0``; i < n; i++) ` `    ``{ ` `        ``// If k is present, then subarray size is 1. ` `        ``if` `(arr[i] == k) ` `            ``return` `1``; ` ` `  `        ``// Break the loop to indicate presence of a ` `        ``// multiple of k. ` `        ``if` `(arr[i] % k == ``0``) ` `            ``found = ``true``; ` `    ``} ` ` `  `    ``// If there was no multiple of k in arr[], then ` `    ``// we can't get k as GCD. ` `    ``if` `(found == ``false``) ` `        ``return` `-``1``; ` ` `  `    ``// If there is a multiple of k in arr[], build ` `    ``// segment tree from given array ` `    ``constructSegmentTree(arr, n); ` ` `  `    ``// Initialize result ` `    ``int` `res = n + ``1``; ` ` `  `    ``// Now consider every element as starting point ` `    ``// and search for ending point using Binary Search ` `    ``for` `(``int` `i = ``0``; i < n - ``1``; i++) ` `    ``{ ` `        ``// a[i] cannot be a starting point, if it is ` `        ``// not a multiple of k. ` `        ``if` `(arr[i] % k != ``0``) ` `            ``continue``; ` ` `  `        ``// Initialize indexes for binary search of closest ` `        ``// ending point to i with GCD of subarray as k. ` `        ``int` `low = i + ``1``; ` `        ``int` `high = n - ``1``; ` ` `  `        ``// Initialize closest ending point for i. ` `        ``int` `closest = ``0``; ` ` `  `        ``// Binary Search for closest ending point ` `        ``// with GCD equal to k. ` `        ``while` `(``true``) ` `        ``{ ` `            ``// Find middle point and GCD of subarray ` `            ``// arr[i..mid] ` `            ``int` `mid = low + (high-low)/``2``; ` `            ``int` `gcd = findRangeGcd(i, mid, arr, n); ` ` `  `            ``// If GCD is more than k, look further ` `            ``if` `(gcd > k) ` `                ``low = mid; ` ` `  `            ``// If GCD is k, store this point and look for ` `            ``// a closer point ` `            ``else` `if` `(gcd == k) ` `            ``{ ` `                ``high = mid; ` `                ``closest = mid; ` `                ``break``; ` `            ``} ` ` `  `            ``// If GCD is less than, look closer ` `            ``else` `                ``high = mid; ` ` `  `            ``// If termination condition reached, set ` `            ``// closest ` `            ``if` `(Math.abs(high-low) <= ``1``) ` `            ``{ ` `                ``if` `(findRangeGcd(i, low, arr, n) == k) ` `                    ``closest = low; ` `                ``else` `if` `(findRangeGcd(i, high, arr, n)==k) ` `                    ``closest = high; ` `                ``break``; ` `            ``} ` `        ``} ` ` `  `        ``if` `(closest != ``0``) ` `            ``res = Math.min(res, closest - i + ``1``); ` `    ``} ` ` `  `    ``// If res was not changed by loop, return -1, ` `    ``// else return its value. ` `    ``return` `(res == n+``1``) ? -``1` `: res; ` `} ` ` `  `// Driver code ` `public` `static` `void` `main(String args[])  ` `{ ` `    ``int` `n = ``8``; ` `    ``int` `k = ``3``; ` `    ``int` `arr[] = {``6``, ``9``, ``7``, ``10``, ``12``, ``24``, ``36``, ``27``}; ` `    ``System.out.println(``"Size of smallest sub-array with given"` `        ``+ ``" size is "` `+ findSmallestSubarr(arr, n, k)); ` `} ` `} ` ` `  `// This code is contributed by Rajput-Ji `

## C#

 `// C# Program to find GCD of a number in a given Range ` `// using segment Trees ` `using` `System; ` ` `  `class` `GFG  ` `{ ` ` `  `// To store segment tree ` `static` `int` `[]st; ` ` `  `// Function to find gcd of 2 numbers. ` `static` `int` `gcd(``int` `a, ``int` `b) ` `{ ` `    ``if` `(a < b) ` `        ``swap(a, b); ` `    ``if` `(b == 0) ` `        ``return` `a; ` `    ``return` `gcd(b, a % b); ` `} ` ` `  `private` `static` `void` `swap(``int` `x, ``int` `y)  ` `{ ` `    ``int` `temp = x; ` `    ``x = y; ` `    ``y = temp; ` `} ` ` `  `/* A recursive function to get gcd of given ` `    ``range of array indexes. The following are parameters for ` `    ``this function. ` ` `  `    ``st --> Pointer to segment tree ` `    ``si --> Index of current node in the segment tree. Initially ` `            ``0 is passed as root is always at index 0 ` `    ``ss & se --> Starting and ending indexes of the segment ` `                ``represented by current node, i.e., st[index] ` `    ``qs & qe --> Starting and ending indexes of query range */` `static` `int` `findGcd(``int` `ss, ``int` `se, ``int` `qs, ``int` `qe, ``int` `si) ` `{ ` `    ``if` `(ss > qe || se < qs) ` `        ``return` `0; ` `    ``if` `(qs <= ss && qe >= se) ` `        ``return` `st[si]; ` `    ``int` `mid = ss + (se - ss) / 2; ` `    ``return` `gcd(findGcd(ss, mid, qs, qe, si * 2 + 1), ` `            ``findGcd(mid + 1, se, qs, qe, si * 2 + 2)); ` `} ` ` `  `// Finding The gcd of given Range ` `static` `int` `findRangeGcd(``int` `ss, ``int` `se, ``int` `[]arr, ``int` `n) ` `{ ` `    ``if` `(ss < 0 || se > n-1 || ss > se) ` `    ``{ ` `        ``Console.WriteLine(``"Invalid Arguments"``); ` `        ``return` `-1; ` `    ``} ` `    ``return` `findGcd(0, n - 1, ss, se, 0); ` `} ` ` `  `// A recursive function that constructs Segment Tree for ` `// array[ss..se]. si is index of current node in segment ` `// tree st ` `static` `int` `constructST(``int` `[]arr, ``int` `ss, ``int` `se, ``int` `si) ` `{ ` `    ``if` `(ss == se) ` `    ``{ ` `        ``st[si] = arr[ss]; ` `        ``return` `st[si]; ` `    ``} ` `    ``int` `mid = ss + (se - ss) / 2; ` `    ``st[si] = gcd(constructST(arr, ss, mid, si * 2 + 1), ` `                ``constructST(arr, mid+1, se, si * 2 + 2)); ` `    ``return` `st[si]; ` `} ` ` `  `/* Function to construct segment tree from given array. ` `This function allocates memory for segment tree and ` `calls constructSTUtil() to fill the allocated memory */` `static` `int` `[]constructSegmentTree(``int` `[]arr, ``int` `n) ` `{ ` `    ``int` `height = (``int``)(Math.Ceiling(Math.Log(n))); ` `    ``int` `size = 2*(``int``)Math.Pow(2, height) - 1; ` `    ``st = ``new` `int``[size]; ` `    ``constructST(arr, 0, n - 1, 0); ` `    ``return` `st; ` `} ` ` `  `// Returns size of smallest subarray of arr[0..n-1] ` `// with GCD equal to k. ` `static` `int` `findSmallestSubarr(``int` `[]arr, ``int` `n, ``int` `k) ` `{ ` `    ``// To check if a multiple of k exists. ` `    ``bool` `found = ``false``; ` ` `  `    ``// Find if k or its multiple is present ` `    ``for` `(``int` `i = 0; i < n; i++) ` `    ``{ ` `        ``// If k is present, then subarray size is 1. ` `        ``if` `(arr[i] == k) ` `            ``return` `1; ` ` `  `        ``// Break the loop to indicate presence of a ` `        ``// multiple of k. ` `        ``if` `(arr[i] % k == 0) ` `            ``found = ``true``; ` `    ``} ` ` `  `    ``// If there was no multiple of k in arr[], then ` `    ``// we can't get k as GCD. ` `    ``if` `(found == ``false``) ` `        ``return` `-1; ` ` `  `    ``// If there is a multiple of k in arr[], build ` `    ``// segment tree from given array ` `    ``constructSegmentTree(arr, n); ` ` `  `    ``// Initialize result ` `    ``int` `res = n + 1; ` ` `  `    ``// Now consider every element as starting point ` `    ``// and search for ending point using Binary Search ` `    ``for` `(``int` `i = 0; i < n - 1; i++) ` `    ``{ ` `        ``// a[i] cannot be a starting point, if it is ` `        ``// not a multiple of k. ` `        ``if` `(arr[i] % k != 0) ` `            ``continue``; ` ` `  `        ``// Initialize indexes for binary search of closest ` `        ``// ending point to i with GCD of subarray as k. ` `        ``int` `low = i + 1; ` `        ``int` `high = n - 1; ` ` `  `        ``// Initialize closest ending point for i. ` `        ``int` `closest = 0; ` ` `  `        ``// Binary Search for closest ending point ` `        ``// with GCD equal to k. ` `        ``while` `(``true``) ` `        ``{ ` `            ``// Find middle point and GCD of subarray ` `            ``// arr[i..mid] ` `            ``int` `mid = low + (high-low)/2; ` `            ``int` `gcd = findRangeGcd(i, mid, arr, n); ` ` `  `            ``// If GCD is more than k, look further ` `            ``if` `(gcd > k) ` `                ``low = mid; ` ` `  `            ``// If GCD is k, store this point and look for ` `            ``// a closer point ` `            ``else` `if` `(gcd == k) ` `            ``{ ` `                ``high = mid; ` `                ``closest = mid; ` `                ``break``; ` `            ``} ` ` `  `            ``// If GCD is less than, look closer ` `            ``else` `                ``high = mid; ` ` `  `            ``// If termination condition reached, set ` `            ``// closest ` `            ``if` `(Math.Abs(high-low) <= 1) ` `            ``{ ` `                ``if` `(findRangeGcd(i, low, arr, n) == k) ` `                    ``closest = low; ` `                ``else` `if` `(findRangeGcd(i, high, arr, n)==k) ` `                    ``closest = high; ` `                ``break``; ` `            ``} ` `        ``} ` ` `  `        ``if` `(closest != 0) ` `            ``res = Math.Min(res, closest - i + 1); ` `    ``} ` ` `  `    ``// If res was not changed by loop, return -1, ` `    ``// else return its value. ` `    ``return` `(res == n+1) ? -1 : res; ` `} ` ` `  `// Driver code ` `public` `static` `void` `Main(String []args)  ` `{ ` `    ``int` `n = 8; ` `    ``int` `k = 3; ` `    ``int` `[]arr = {6, 9, 7, 10, 12, 24, 36, 27}; ` `    ``Console.WriteLine(``"Size of smallest sub-array with given"` `        ``+ ``" size is "` `+ findSmallestSubarr(arr, n, k)); ` `} ` `} ` ` `  `/* This code is contributed by PrinciRaj1992 */`

Output:

`Size of smallest sub-array with given size is 2`

Example:

```arr[] = {6, 9, 7, 10, 12, 24, 36, 27}, K = 3

// Initial value of minLen is equal to size
// of array
minLen = 8

No element is equal to k so result is either
greater than 1 or doesn't exist. ```

First index

• GCD of subarray from 1 to 5 is 1.
• GCD < k
• GCD of subarray from 1 to 3 is 1.
• GCD < k
• GCD of subarray from 1 to 2 is 3
• minLen = minimum(8, 2) = 2

Second Index

• GCD of subarray from 2 to 5 is 1
• GCD < k
• GCD of subarray from 2 to 4 is 1
• GCD < k
• GCD of subarray from 6 to 8 is 3
• minLen = minimum(2, 3) = 2.

.

.

.

Sixth Index

• GCD of subarray from 6 to 7 is 12
• GCD > k
• GCD of subarray from 6 to 8 is 3
• minLen = minimum(2, 3) = 2

Time Complexity: O(n (logn)2), O(n) for traversing to each index, O(logn) for each subarray and O(logn) for GCD of each subarray.

This article is contributed by Nikhil Tekwani. If you like GeeksforGeeks and would like to contribute, you can also write an article and mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.