# Smallest subarray with GCD as 1 | Segment Tree

• Difficulty Level : Hard
• Last Updated : 25 Jan, 2023

Given an array arr[], the task is to find the smallest sub-arrays with GCD equal to 1. If there is no such sub-array then print -1.

Examples:

Input: arr[] = {2, 6, 3}
Output:
{2, 6, 3} is the only sub-array with GCD = 1.

Input: arr[] = {2, 2, 2}
Output: -1

Approach: This problem can be solved in O(NlogN) using a segment-tree data structure. The segment that will be built can be used to answer range-gcd queries.

Let’s understand the algorithm now. Use the two-pointer technique to solve this problem. Let’s make a few observations before discussing the algorithm.

• Let’s say G is the GCD of the subarray arr[l…r] and G1 is the GCD of the subarray arr[l+1…r]. G smaller than or equal to G1 always.
• Let’s say for the given L1, R1 is the first index such that GCD of the range [L, R] is 1 than for any L2 greater than or equal to L1, R2 will also be greater than or equal to R1.

After the above observation, the two-pointer technique makes perfect sense i.e. if the length of the smallest R is known for an index L then for an index L + 1, the search needs to be started from R on-wards.

Below is the implementation of the above approach:

## C++

 `// C++ implementation of the approach``#include ``using` `namespace` `std;``#define maxLen 30` `// Array to store segment-tree``int` `seg[3 * maxLen];` `// Function to build segment-tree to``// answer range GCD queries``int` `build(``int` `l, ``int` `r, ``int` `in, ``int``* arr)``{``    ``// Base-case``    ``if` `(l == r)``        ``return` `seg[in] = arr[l];` `    ``// Mid element of the range``    ``int` `mid = (l + r) / 2;` `    ``// Merging the result of left and right sub-tree``    ``return` `seg[in] = __gcd(build(l, mid, 2 * in + 1, arr),``                           ``build(mid + 1, r, 2 * in + 2, arr));``}` `// Function to perform range GCD queries``int` `query(``int` `l, ``int` `r, ``int` `l1, ``int` `r1, ``int` `in)``{``    ``// Base-cases``    ``if` `(l1 <= l and r <= r1)``        ``return` `seg[in];``    ``if` `(l > r1 or r < l1)``        ``return` `0;` `    ``// Mid-element``    ``int` `mid = (l + r) / 2;` `    ``// Calling left and right child``    ``return` `__gcd(query(l, mid, l1, r1, 2 * in + 1),``                 ``query(mid + 1, r, l1, r1, 2 * in + 2));``}` `// Function to find the required length``int` `findLen(``int``* arr, ``int` `n)``{``    ``// Building the segment tree``    ``build(0, n - 1, 0, arr);` `    ``// Two pointer variables``    ``int` `i = 0, j = 0;` `    ``// To store the final answer``    ``int` `ans = INT_MAX;` `    ``// Looping``    ``while` `(i < n) {` `        ``// Incrementing j till we don't get``        ``// a gcd value of 1``        ``while` `(j < n and query(0, n - 1, i, j, 0) != 1)``            ``j++;` `        ``if` `(j == n)``            ``break``;` `        ``// Updating the final answer``        ``ans = min((j - i + 1), ans);` `        ``// Incrementing i``        ``i++;` `        ``// Updating j``        ``j = max(j, i);``    ``}` `    ``// Returning the final answer``    ``if` `(ans == INT_MAX)``        ``return` `-1;``    ``else``        ``return` `ans;``}` `// Driver code``int` `main()``{``    ``int` `arr[] = { 2, 2, 2 };``    ``int` `n = ``sizeof``(arr) / ``sizeof``(``int``);` `    ``cout << findLen(arr, n);` `    ``return` `0;``}`

## Java

 `// Java implementation of the approach``class` `GFG``{``static` `int` `maxLen = ``30``;` `// Array to store segment-tree``static` `int` `[]seg = ``new` `int``[``3` `* maxLen];` `// Function to build segment-tree to``// answer range GCD queries``static` `int` `build(``int` `l, ``int` `r,``                 ``int` `in, ``int``[] arr)``{``    ``// Base-case``    ``if` `(l == r)``        ``return` `seg[in] = arr[l];` `    ``// Mid element of the range``    ``int` `mid = (l + r) / ``2``;` `    ``// Merging the result of left and right sub-tree``    ``return` `seg[in] = __gcd(build(l, mid, ``2` `* in + ``1``, arr),``                           ``build(mid + ``1``, r, ``2` `* in + ``2``, arr));``}` `// Function to perform range GCD queries``static` `int` `query(``int` `l, ``int` `r,``                 ``int` `l1, ``int` `r1, ``int` `in)``{``    ``// Base-cases``    ``if` `(l1 <= l && r <= r1)``        ``return` `seg[in];``    ``if` `(l > r1 || r < l1)``        ``return` `0``;` `    ``// Mid-element``    ``int` `mid = (l + r) / ``2``;` `    ``// Calling left and right child``    ``return` `__gcd(query(l, mid, l1, r1, ``2` `* in + ``1``),``                 ``query(mid + ``1``, r, l1, r1, ``2` `* in + ``2``));``}` `// Function to find the required length``static` `int` `findLen(``int` `[]arr, ``int` `n)``{``    ``// Building the segment tree``    ``build(``0``, n - ``1``, ``0``, arr);` `    ``// Two pointer variables``    ``int` `i = ``0``, j = ``0``;` `    ``// To store the final answer``    ``int` `ans = Integer.MAX_VALUE;` `    ``// Looping``    ``while` `(i < n)``    ``{` `        ``// Incrementing j till we don't get``        ``// a gcd value of 1``        ``while` `(j < n && query(``0``, n - ``1``,``                              ``i, j, ``0``) != ``1``)``            ``j++;` `        ``if` `(j == n)``            ``break``;` `        ``// Updating the final answer``        ``ans = Math.min((j - i + ``1``), ans);` `        ``// Incrementing i``        ``i++;` `        ``// Updating j``        ``j = Math.max(j, i);``    ``}` `    ``// Returning the final answer``    ``if` `(ans == Integer.MAX_VALUE)``        ``return` `-``1``;``    ``else``        ``return` `ans;``}` `static` `int` `__gcd(``int` `a, ``int` `b)``{``    ``return` `b == ``0` `? a : __gcd(b, a % b);    ``}` `// Driver code``public` `static` `void` `main(String[] args)``{``    ``int` `arr[] = { ``2``, ``2``, ``2` `};``    ``int` `n = arr.length;` `    ``System.out.println(findLen(arr, n));``}``}` `// This code is contributed by 29AjayKumar`

## Python3

 `# Python3 implementation of the approach``from` `math ``import` `gcd as __gcd` `maxLen ``=` `30` `# Array to store segment-tree``seg ``=` `[``0` `for` `i ``in` `range``(``3` `*` `maxLen)]` `# Function to build segment-tree to``# answer range GCD queries``def` `build(l, r, inn, arr):``    ` `    ``# Base-case``    ``if` `(l ``=``=` `r):``        ``seg[inn] ``=` `arr[l]``        ``return` `seg[inn]` `    ``# Mid element of the range``    ``mid ``=` `(l ``+` `r) ``/``/` `2` `    ``# Merging the result of``    ``# left and right sub-tree``    ``seg[inn] ``=` `__gcd(build(l, mid,``                           ``2` `*` `inn ``+` `1``, arr),``                     ``build(mid ``+` `1``, r,``                           ``2` `*` `inn ``+` `2``, arr))` `    ``return` `seg[inn]` `# Function to perform range GCD queries``def` `query(l, r, l1, r1, inn):``    ` `    ``# Base-cases``    ``if` `(l1 <``=` `l ``and` `r <``=` `r1):``        ``return` `seg[inn]``    ``if` `(l > r1 ``or` `r < l1):``        ``return` `0` `    ``# Mid-element``    ``mid ``=` `(l ``+` `r) ``/``/` `2` `    ``# Calling left and right child``    ``x``=``__gcd(query(l, mid, l1, r1,``                  ``2` `*` `inn ``+` `1``),``            ``query(mid ``+` `1``, r, l1, r1,``                  ``2` `*` `inn ``+` `2``))``    ``return` `x` `# Function to find the required length``def` `findLen(arr, n):``    ` `    ``# Building the segment tree``    ``build(``0``, n ``-` `1``, ``0``, arr)` `    ``# Two pointer variables``    ``i ``=` `0``    ``j ``=` `0` `    ``# To store the final answer``    ``ans ``=` `10``*``*``9` `    ``# Loopinng``    ``while` `(i < n):` `        ``# Incrementing j till we``        ``# don't get a gcd value of 1``        ``while` `(j < n ``and` `query(``0``, n ``-` `1``,``                               ``i, j, ``0``) !``=` `1``):``            ``j ``+``=` `1` `        ``if` `(j ``=``=` `n):``            ``break``;` `        ``# Updating the final answer``        ``ans ``=` `minn((j ``-` `i ``+` `1``), ans)` `        ``# Incrementing i``        ``i ``+``=` `1` `        ``# Updating j``        ``j ``=` `max``(j, i)` `    ``# Returning the final answer``    ``if` `(ans ``=``=` `10``*``*``9``):``        ``return` `-``1``    ``else``:``        ``return` `ans` `# Driver code``arr ``=` `[``2``, ``2``, ``2``]``n ``=` `len``(arr)` `print``(findLen(arr, n))` `# This code is contributed by Mohit Kumar`

## C#

 `// C# implementation of the approach``using` `System;` `class` `GFG``{``    ``static` `int` `maxLen = 30;``    ` `    ``// Array to store segment-tree``    ``static` `int` `[]seg = ``new` `int``[3 * maxLen];``    ` `    ``// Function to build segment-tree to``    ``// answer range GCD queries``    ``static` `int` `build(``int` `l, ``int` `r,``                     ``int` `ind, ``int``[] arr)``    ``{``        ``// Base-case``        ``if` `(l == r)``            ``return` `seg[ind] = arr[l];``    ` `        ``// Mid element of the range``        ``int` `mid = (l + r) / 2;``    ` `        ``// Merging the result of left and right sub-tree``        ``return` `seg[ind] = __gcd(build(l, mid, 2 * ind + 1, arr),``                                ``build(mid + 1, r, 2 * ind + 2, arr));``    ``}``    ` `    ``// Function to perform range GCD queries``    ``static` `int` `query(``int` `l, ``int` `r,``                     ``int` `l1, ``int` `r1, ``int` `ind)``    ``{``        ``// Base-cases``        ``if` `(l1 <= l && r <= r1)``            ``return` `seg[ind];``        ``if` `(l > r1 || r < l1)``            ``return` `0;``    ` `        ``// Mid-element``        ``int` `mid = (l + r) / 2;``    ` `        ``// Calling left and right child``        ``return` `__gcd(query(l, mid, l1, r1, 2 * ind + 1),``                     ``query(mid + 1, r, l1, r1, 2 * ind + 2));``    ``}``    ` `    ``// Function to find the required length``    ``static` `int` `findLen(``int` `[]arr, ``int` `n)``    ``{``        ``// Building the segment tree``        ``build(0, n - 1, 0, arr);``    ` `        ``// Two pointer variables``        ``int` `i = 0, j = 0;``    ` `        ``// To store the final answer``        ``int` `ans = ``int``.MaxValue;``    ` `        ``// Looping``        ``while` `(i < n)``        ``{``    ` `            ``// Incrementing j till we don't get``            ``// a gcd value of 1``            ``while` `(j < n && query(0, n - 1,``                                  ``i, j, 0) != 1)``                ``j++;``    ` `            ``if` `(j == n)``                ``break``;``    ` `            ``// Updating the final answer``            ``ans = Math.Min((j - i + 1), ans);``    ` `            ``// Incrementing i``            ``i++;``    ` `            ``// Updating j``            ``j = Math.Max(j, i);``        ``}``    ` `        ``// Returning the final answer``        ``if` `(ans == ``int``.MaxValue)``            ``return` `-1;``        ``else``            ``return` `ans;``    ``}``    ` `    ``static` `int` `__gcd(``int` `a, ``int` `b)``    ``{``        ``return` `b == 0 ? a : __gcd(b, a % b);    ``    ``}``    ` `    ``// Driver code``    ``public` `static` `void` `Main()``    ``{``        ``int` `[]arr = { 2, 2, 2 };``        ``int` `n = arr.Length;``    ` `        ``Console.WriteLine(findLen(arr, n));``    ``}``}` `// This code is contributed by kanugargng`

## Javascript

 ``

Output:

`-1`

Time complexity :   O(n log n)
Auxiliary Space :  O(n), as the size of the segment tree is O(n).

My Personal Notes arrow_drop_up