Smallest Subarray with given GCD

Last Updated : 2 Aug, 2026

Given an array arr[] and an integer , 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

Try It Yourself
redirect icon

[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.

C++
#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
// 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
# 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#
// 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
// 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
C++
#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
// 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
# 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#
// 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
// 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
Comment