Given an array arr[] and an integer k , find the length of the smallest subarray whose Greatest Common Divisor equals k.
Note: If no such subarray exists, return -1.
Examples:
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.Input: arr[] = [9, 12, 15, 24, 36, 27], k = 2
Output: -1
Explanation: GCD 2 is not possible from any subarray from the given array.Input: arr[] = [1, 2, 4, 8], k = 1
Output: 1
[Naive Approach] Nested Loop with GCD - O(n² log M) Time and O(1) Space
The idea is based on the fact that adding more elements to a subarray never increases overall GCD.
For each starting index, extend subarray and track GCD. If GCD becomes less than k, break early. If GCD equals k, update minimum length.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// Function to compute GCD of two numbers
int findGCD(int a, int b) {
if (b == 0)
return a;
return findGCD(b, a % b);
}
// Function to find the minimum length of subarray
// whose GCD is exactly k
int findSmallestSubArr(vector<int>& arr, int k) {
int n = arr.size();
int minLen = n + 1;
// Iterate over all possible subarrays
for (int i = 0; i < n; i++) {
int currGCD = 0;
for (int j = i; j < n; j++) {
// Update GCD of current subarray
currGCD = findGCD(currGCD, arr[j]);
// If current GCD becomes less than k, break early
if (currGCD < k)
break;
// If GCD equals k, update minLen
if (currGCD == k) {
minLen = min(minLen, j - i + 1);
break;
}
}
}
// If no valid subarray found, return -1
return (minLen == n + 1) ? -1 : minLen;
}
int main() {
vector<int> arr = {6, 9, 7, 10, 12, 24, 36, 27};
int k = 3;
cout << findSmallestSubArr(arr, k) << endl;
return 0;
}
// Java program to find smallest subarray whose GCD is exactly k
import java.util.*;
class GfG {
// Function to compute GCD of two numbers
static int findGCD(int a, int b) {
if (b == 0)
return a;
return findGCD(b, a % b);
}
// Function to find the minimum length of subarray whose GCD is exactly k
static int findSmallestSubArr(int[] arr, int k) {
int n = arr.length;
int minLen = n + 1;
// Iterate over all possible subarrays
for (int i = 0; i < n; i++) {
int currGCD = 0;
for (int j = i; j < n; j++) {
// Update GCD of current subarray
currGCD = findGCD(currGCD, arr[j]);
// If current GCD becomes less than k, break early
if (currGCD < k)
break;
// If GCD equals k, update minLen
if (currGCD == k) {
minLen = Math.min(minLen, j - i + 1);
break;
}
}
}
// If no valid subarray found, return -1
return (minLen == n + 1) ? -1 : minLen;
}
public static void main(String[] args) {
int[] arr = {6, 9, 7, 10, 12, 24, 36, 27};
int k = 3;
System.out.println(findSmallestSubArr(arr, k));
}
}
# Python program to find smallest subarray whose GCD is exactly k
# Function to compute GCD of two numbers
def findGCD(a, b):
if b == 0:
return a
return findGCD(b, a % b)
# Function to find the minimum length of subarray whose GCD is exactly k
def findSmallestSubArr(arr, k):
n = len(arr)
minLen = n + 1
# Iterate over all possible subarrays
for i in range(n):
currGCD = 0
for j in range(i, n):
# Update GCD of current subarray
currGCD = findGCD(currGCD, arr[j])
# If current GCD becomes less than k, break early
if currGCD < k:
break
# If GCD equals k, update minLen
if currGCD == k:
minLen = min(minLen, j - i + 1)
break
# If no valid subarray found, return -1
return -1 if minLen == n + 1 else minLen
# Driver code
if __name__ == "__main__":
arr = [6, 9, 7, 10, 12, 24, 36, 27]
k = 3
print(findSmallestSubArr(arr, k))
// C# program to find smallest subarray whose GCD is exactly k
using System;
class GfG {
// Function to compute GCD of two numbers
static int findGCD(int a, int b) {
if (b == 0)
return a;
return findGCD(b, a % b);
}
// Function to find the minimum length of subarray whose GCD is exactly k
static int findSmallestSubArr(int[] arr, int k) {
int n = arr.Length;
int minLen = n + 1;
// Iterate over all possible subarrays
for (int i = 0; i < n; i++) {
int currGCD = 0;
for (int j = i; j < n; j++) {
// Update GCD of current subarray
currGCD = findGCD(currGCD, arr[j]);
// If current GCD becomes less than k, break early
if (currGCD < k)
break;
// If GCD equals k, update minLen
if (currGCD == k) {
minLen = Math.Min(minLen, j - i + 1);
break;
}
}
}
// If no valid subarray found, return -1
return (minLen == n + 1) ? -1 : minLen;
}
static void Main(string[] args) {
int[] arr = {6, 9, 7, 10, 12, 24, 36, 27};
int k = 3;
Console.WriteLine(findSmallestSubArr(arr, k));
}
}
// JavaScript program to find smallest subarray whose GCD is exactly k
// Function to compute GCD of two numbers
function findGCD(a, b) {
if (b === 0)
return a;
return findGCD(b, a % b);
}
// Function to find the minimum length of subarray whose GCD is exactly k
function findSmallestSubArr(arr, k) {
const n = arr.length;
let minLen = n + 1;
// Iterate over all possible subarrays
for (let i = 0; i < n; i++) {
let currGCD = 0;
for (let j = i; j < n; j++) {
// Update GCD of current subarray
currGCD = findGCD(currGCD, arr[j]);
// If current GCD becomes less than k, break early
if (currGCD < k)
break;
// If GCD equals k, update minLen
if (currGCD === k) {
minLen = Math.min(minLen, j - i + 1);
break;
}
}
}
// If no valid subarray found, return -1
return (minLen === n + 1) ? -1 : minLen;
}
// Driver code
const arr = [6, 9, 7, 10, 12, 24, 36, 27];
const k = 3;
console.log(findSmallestSubArr(arr, k));
Output
2
[Expected Approach] Segment Tree with Binary Search - O(n log² n) Time and O(n) Space
Build segment tree for range GCD queries. For each starting index, binary search ending index where GCD becomes k. GCD is non-increasing as subarray expands, enabling binary search.
- Build segment tree to answer range GCD queries in O(log n)
- For each i from 0 to n-1
- Binary search on end index to find first position where GCD == k
- If GCD at mid > k, move right
- If GCD at mid < k, move left
- If GCD == k, update answer and search left for smaller length
- Return minimum length found
#include <bits/stdc++.h>
using namespace std;
int gcdUtil(int a, int b) {
return b == 0 ? a : gcdUtil(b, a % b);
}
void build(vector<int>& seg, vector<int>& arr, int idx, int l, int r) {
if (l == r) {
seg[idx] = arr[l];
return;
}
int mid = (l + r) / 2;
build(seg, arr, 2 * idx + 1, l, mid);
build(seg, arr, 2 * idx + 2, mid + 1, r);
seg[idx] = gcdUtil(seg[2 * idx + 1], seg[2 * idx + 2]);
}
int query(vector<int>& seg, int idx, int l, int r, int ql, int qr) {
if (ql > r || qr < l)
return 0;
if (ql <= l && r <= qr)
return seg[idx];
int mid = (l + r) / 2;
return gcdUtil(
query(seg, 2 * idx + 1, l, mid, ql, qr),
query(seg, 2 * idx + 2, mid + 1, r, ql, qr)
);
}
int findSmallestSubArr(vector<int>& arr, int k) {
int n = arr.size();
vector<int> seg(4 * n);
build(seg, arr, 0, 0, n - 1);
int ans = n + 1;
for (int i = 0; i < n; i++) {
int low = i, high = n - 1;
int pos = -1;
while (low <= high) {
int mid = low + (high - low) / 2;
int g = query(seg, 0, 0, n - 1, i, mid);
if (g > k)
low = mid + 1;
else if (g < k)
high = mid - 1;
else {
pos = mid;
high = mid - 1;
}
}
if (pos != -1)
ans = min(ans, pos - i + 1);
}
return ans == n + 1 ? -1 : ans;
}
int main() {
vector<int> arr = {6, 9, 7, 10, 12, 24, 36, 27};
int k = 3;
cout << findSmallestSubArr(arr, k);
return 0;
}
// Java program to find smallest subarray whose GCD is exactly k using Segment Tree
import java.util.*;
class GfG {
static int gcdUtil(int a, int b) {
return b == 0 ? a : gcdUtil(b, a % b);
}
static void build(int[] seg, int[] arr, int idx, int l, int r) {
if (l == r) {
seg[idx] = arr[l];
return;
}
int mid = (l + r) / 2;
build(seg, arr, 2 * idx + 1, l, mid);
build(seg, arr, 2 * idx + 2, mid + 1, r);
seg[idx] = gcdUtil(seg[2 * idx + 1], seg[2 * idx + 2]);
}
static int query(int[] seg, int idx, int l, int r, int ql, int qr) {
if (ql > r || qr < l)
return 0;
if (ql <= l && r <= qr)
return seg[idx];
int mid = (l + r) / 2;
return gcdUtil(
query(seg, 2 * idx + 1, l, mid, ql, qr),
query(seg, 2 * idx + 2, mid + 1, r, ql, qr)
);
}
static int findSmallestSubArr(int[] arr, int k) {
int n = arr.length;
int[] seg = new int[4 * n];
build(seg, arr, 0, 0, n - 1);
int ans = n + 1;
for (int i = 0; i < n; i++) {
int low = i, high = n - 1;
int pos = -1;
while (low <= high) {
int mid = low + (high - low) / 2;
int g = query(seg, 0, 0, n - 1, i, mid);
if (g > k) {
low = mid + 1;
} else if (g < k) {
high = mid - 1;
} else {
pos = mid;
high = mid - 1;
}
}
if (pos != -1) {
ans = Math.min(ans, pos - i + 1);
}
}
return ans == n + 1 ? -1 : ans;
}
public static void main(String[] args) {
int[] arr = {6, 9, 7, 10, 12, 24, 36, 27};
int k = 3;
System.out.println(findSmallestSubArr(arr, k));
}
}
# Python program to find smallest subarray whose GCD is exactly k using Segment Tree
def gcdUtil(a, b):
return a if b == 0 else gcdUtil(b, a % b)
def build(seg, arr, idx, l, r):
if l == r:
seg[idx] = arr[l]
return
mid = (l + r) // 2
build(seg, arr, 2 * idx + 1, l, mid)
build(seg, arr, 2 * idx + 2, mid + 1, r)
seg[idx] = gcdUtil(seg[2 * idx + 1], seg[2 * idx + 2])
def query(seg, idx, l, r, ql, qr):
if ql > r or qr < l:
return 0
if ql <= l and r <= qr:
return seg[idx]
mid = (l + r) // 2
return gcdUtil(
query(seg, 2 * idx + 1, l, mid, ql, qr),
query(seg, 2 * idx + 2, mid + 1, r, ql, qr)
)
def findSmallestSubArr(arr, k):
n = len(arr)
seg = [0] * (4 * n)
build(seg, arr, 0, 0, n - 1)
ans = n + 1
for i in range(n):
low, high = i, n - 1
pos = -1
while low <= high:
mid = low + (high - low) // 2
g = query(seg, 0, 0, n - 1, i, mid)
if g > k:
low = mid + 1
elif g < k:
high = mid - 1
else:
pos = mid
high = mid - 1
if pos != -1:
ans = min(ans, pos - i + 1)
return -1 if ans == n + 1 else ans
# Driver code
if __name__ == "__main__":
arr = [6, 9, 7, 10, 12, 24, 36, 27]
k = 3
print(findSmallestSubArr(arr, k))
// C# program to find smallest subarray whose GCD is exactly k using Segment Tree
using System;
class GfG {
static int gcdUtil(int a, int b) {
return b == 0 ? a : gcdUtil(b, a % b);
}
static void build(int[] seg, int[] arr, int idx, int l, int r) {
if (l == r) {
seg[idx] = arr[l];
return;
}
int mid = (l + r) / 2;
build(seg, arr, 2 * idx + 1, l, mid);
build(seg, arr, 2 * idx + 2, mid + 1, r);
seg[idx] = gcdUtil(seg[2 * idx + 1], seg[2 * idx + 2]);
}
static int query(int[] seg, int idx, int l, int r, int ql, int qr) {
if (ql > r || qr < l)
return 0;
if (ql <= l && r <= qr)
return seg[idx];
int mid = (l + r) / 2;
return gcdUtil(
query(seg, 2 * idx + 1, l, mid, ql, qr),
query(seg, 2 * idx + 2, mid + 1, r, ql, qr)
);
}
static int findSmallestSubArr(int[] arr, int k) {
int n = arr.Length;
int[] seg = new int[4 * n];
build(seg, arr, 0, 0, n - 1);
int ans = n + 1;
for (int i = 0; i < n; i++) {
int low = i, high = n - 1;
int pos = -1;
while (low <= high) {
int mid = low + (high - low) / 2;
int g = query(seg, 0, 0, n - 1, i, mid);
if (g > k) {
low = mid + 1;
} else if (g < k) {
high = mid - 1;
} else {
pos = mid;
high = mid - 1;
}
}
if (pos != -1) {
ans = Math.Min(ans, pos - i + 1);
}
}
return ans == n + 1 ? -1 : ans;
}
static void Main(string[] args) {
int[] arr = {6, 9, 7, 10, 12, 24, 36, 27};
int k = 3;
Console.WriteLine(findSmallestSubArr(arr, k));
}
}
// JavaScript program to find smallest subarray whose GCD is exactly k using Segment Tree
function gcdUtil(a, b) {
return b === 0 ? a : gcdUtil(b, a % b);
}
function build(seg, arr, idx, l, r) {
if (l === r) {
seg[idx] = arr[l];
return;
}
const mid = Math.floor((l + r) / 2);
build(seg, arr, 2 * idx + 1, l, mid);
build(seg, arr, 2 * idx + 2, mid + 1, r);
seg[idx] = gcdUtil(seg[2 * idx + 1], seg[2 * idx + 2]);
}
function query(seg, idx, l, r, ql, qr) {
if (ql > r || qr < l)
return 0;
if (ql <= l && r <= qr)
return seg[idx];
const mid = Math.floor((l + r) / 2);
return gcdUtil(
query(seg, 2 * idx + 1, l, mid, ql, qr),
query(seg, 2 * idx + 2, mid + 1, r, ql, qr)
);
}
function findSmallestSubArr(arr, k) {
const n = arr.length;
const seg = new Array(4 * n);
build(seg, arr, 0, 0, n - 1);
let ans = n + 1;
for (let i = 0; i < n; i++) {
let low = i, high = n - 1;
let pos = -1;
while (low <= high) {
const mid = low + Math.floor((high - low) / 2);
const g = query(seg, 0, 0, n - 1, i, mid);
if (g > k) {
low = mid + 1;
} else if (g < k) {
high = mid - 1;
} else {
pos = mid;
high = mid - 1;
}
}
if (pos !== -1) {
ans = Math.min(ans, pos - i + 1);
}
}
return ans === n + 1 ? -1 : ans;
}
// Driver code
const arr = [6, 9, 7, 10, 12, 24, 36, 27];
const k = 3;
console.log(findSmallestSubArr(arr, k));
Output
2