Open In App

GCD Traversal

Last Updated : 11 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given array nums, you are allowed to traverse between its indices. You can traverse between index i and index j, i!= j, if and only if gcd(nums[i], nums[j]) > 1, where gcd is the greatest common divisor.

Your task is to determine if for every pair of indices i and j in nums, where i < j, there exists a sequence of traversals that can take us from i to j. Return true if it is possible to traverse between all such pairs of indices, or false otherwise.

Examples:

Input: nums = [4,3,12,8] N=4
Output: true (1)
Explanation: Possible pairs: (0, 1), (0, 2), (0, 3), (1, 2), (1, 3), and (2, 3). Sequence exists for each pair, so we return true.

Input: nums = [3,9,5] N=3
Output: false (0)
Explanation: No sequence of traversals from 0 to 2. So, we return false.

Approach: To solve the problem follow the below idea:

The approach used for GCD traversal is Union-Find.

Steps to solve the problem:

  • Disjoint Set Union (Union-Find): The findParent and uniteSets functions implement the Union-Find data structure. This structure is used to efficiently determine the connectivity of elements in a set.
  • The canTraverseAllPairs function iterates through the elements of the nums vector.
  • It then uses the Union-Find operations (findParent and uniteSets) to merge sets of indices that share common prime factors. The factorsMap is used to keep track of the indices associated with each prime factor.
  • Check Final Connectivity: After processing all elements, the function checks whether all elements are part of a single connected component in the Union-Find structure. This is done by checking the size of the set containing the representative of the first element (0).

Below is the code for the above approach:

C++




#include <bits/stdc++.h>
using namespace std;
 
int findParent(vector<int>& parent, int node)
{
    return parent[node] == node
               ? node
               : (parent[node]
                  = findParent(parent, parent[node]));
}
 
void uniteSets(vector<int>& parent, vector<int>& size,
               int node1, int node2)
{
    node1 = findParent(parent, node1);
    node2 = findParent(parent, node2);
    if (node1 == node2) {
        return;
    }
    if (size[node1] < size[node2]) {
        swap(node1, node2);
    }
    parent[node2] = node1;
    size[node1] += size[node2];
}
 
bool canTraverseAllPairs(vector<int>& nums)
{
    const int n = nums.size();
    if (n == 1) {
        return true;
    }
    vector<int> parent(n), size(n);
    for (int i = 0; i < n; ++i) {
        parent[i] = i;
        size[i] = 1;
    }
    unordered_map<int, int> factorsMap;
    for (int i = 0; i < n; ++i) {
        int x = nums[i];
        if (x == 1) {
            return false;
        }
        for (int factor = 2; factor * factor <= x;
             ++factor) {
            if (x % factor == 0) {
                if (factorsMap.count(factor)) {
                    uniteSets(parent, size, i,
                              factorsMap[factor]);
                }
                else {
                    factorsMap[factor] = i;
                }
                while (x % factor == 0) {
                    x /= factor;
                }
            }
        }
        if (x > 1) {
            if (factorsMap.count(x)) {
                uniteSets(parent, size, i, factorsMap[x]);
            }
            else {
                factorsMap[x] = i;
            }
        }
    }
    return size[findParent(parent, 0)] == n;
}
 
int main()
{
    vector<int> nums = { 4, 3, 12, 8 };
    // Check if it is possible to traverse all pairs
    bool result = canTraverseAllPairs(nums);
    // displaying the result
    cout << result;
    return 0;
}


Java




import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
public class GFG {
    static int findParent(List<Integer> parent, int node) {
        return parent.get(node) == node ? node : findParent(parent, parent.get(node));
    }
 
    static void uniteSets(List<Integer> parent, List<Integer> size, int node1, int node2) {
        node1 = findParent(parent, node1);
        node2 = findParent(parent, node2);
        if (node1 == node2) {
            return;
        }
        if (size.get(node1) < size.get(node2)) {
            int temp = node1;
            node1 = node2;
            node2 = temp;
        }
        parent.set(node2, node1);
        size.set(node1, size.get(node1) + size.get(node2));
    }
 
    static boolean canTraverseAllPairs(List<Integer> nums) {
        int n = nums.size();
        if (n == 1) {
            return true;
        }
        List<Integer> parent = new ArrayList<>(n);
        List<Integer> size = new ArrayList<>(n);
        for (int i = 0; i < n; ++i) {
            parent.add(i);
            size.add(1);
        }
        Map<Integer, Integer> factorsMap = new HashMap<>();
        for (int i = 0; i < n; ++i) {
            int x = nums.get(i);
            if (x == 1) {
                return false;
            }
            for (int factor = 2; factor * factor <= x; ++factor) {
                if (x % factor == 0) {
                    if (factorsMap.containsKey(factor)) {
                        uniteSets(parent, size, i, factorsMap.get(factor));
                    } else {
                        factorsMap.put(factor, i);
                    }
                    while (x % factor == 0) {
                        x /= factor;
                    }
                }
            }
            if (x > 1) {
                if (factorsMap.containsKey(x)) {
                    uniteSets(parent, size, i, factorsMap.get(x));
                } else {
                    factorsMap.put(x, i);
                }
            }
        }
        return size.get(findParent(parent, 0)) == n;
    }
 
    public static void main(String[] args) {
        List<Integer> nums = new ArrayList<>();
        nums.add(4);
        nums.add(3);
        nums.add(12);
        nums.add(8);
 
        // Check if it is possible to traverse all pairs
        boolean result = canTraverseAllPairs(nums);
 
        // Displaying the result
        if (result) {
            System.out.println(1);
        } else {
            System.out.println(0);
        }
    }
}


Python3




def find_parent(parent, node):
    if parent[node] == node:
        return node
    parent[node] = find_parent(parent, parent[node])
    return parent[node]
 
def unite_sets(parent, size, node1, node2):
    node1 = find_parent(parent, node1)
    node2 = find_parent(parent, node2)
    if node1 == node2:
        return
    if size[node1] < size[node2]:
        node1, node2 = node2, node1
    parent[node2] = node1
    size[node1] += size[node2]
 
def can_traverse_all_pairs(nums):
    n = len(nums)
    if n == 1:
        return 1  # Returning 1 for True
    parent = list(range(n))
    size = [1] * n
    factors_map = {}
    for i in range(n):
        x = nums[i]
        if x == 1:
            return 0  # Returning 0 for False
        for factor in range(2, int(x ** 0.5) + 1):
            if x % factor == 0:
                if factor in factors_map:
                    unite_sets(parent, size, i, factors_map[factor])
                else:
                    factors_map[factor] = i
                while x % factor == 0:
                    x //= factor
        if x > 1:
            if x in factors_map:
                unite_sets(parent, size, i, factors_map[x])
            else:
                factors_map[x] = i
    return int(size[find_parent(parent, 0)] == n)  # Returning 1 or 0 based on condition
 
def main():
    nums = [4, 3, 12, 8]
    # Check if it is possible to traverse all pairs
    result = can_traverse_all_pairs(nums)
    # displaying the result
    print(result)
 
if __name__ == "__main__":
    main()


C#




using System;
using System.Collections.Generic;
 
public class GFG {
    static int FindParent(List<int> parent, int node)
    {
        return parent[node] == node
            ? node
            : (parent[node]
               = FindParent(parent, parent[node]));
    }
 
    static void UniteSets(List<int> parent, List<int> size,
                          int node1, int node2)
    {
        node1 = FindParent(parent, node1);
        node2 = FindParent(parent, node2);
        if (node1 == node2) {
            return;
        }
        if (size[node1] < size[node2]) {
            int temp = node1;
            node1 = node2;
            node2 = temp;
        }
        parent[node2] = node1;
        size[node1] += size[node2];
    }
 
    static bool CanTraverseAllPairs(List<int> nums)
    {
        int n = nums.Count;
        if (n == 1) {
            return true;
        }
        List<int> parent = new List<int>(n);
        List<int> size = new List<int>(n);
        for (int i = 0; i < n; ++i) {
            parent.Add(i);
            size.Add(1);
        }
        Dictionary<int, int> factorsMap
            = new Dictionary<int, int>();
        for (int i = 0; i < n; ++i) {
            int x = nums[i];
            if (x == 1) {
                return false;
            }
            for (int factor = 2; factor * factor <= x;
                 ++factor) {
                if (x % factor == 0) {
                    if (factorsMap.ContainsKey(factor)) {
                        UniteSets(parent, size, i,
                                  factorsMap[factor]);
                    }
                    else {
                        factorsMap[factor] = i;
                    }
                    while (x % factor == 0) {
                        x /= factor;
                    }
                }
            }
            if (x > 1) {
                if (factorsMap.ContainsKey(x)) {
                    UniteSets(parent, size, i,
                              factorsMap[x]);
                }
                else {
                    factorsMap[x] = i;
                }
            }
        }
        return size[FindParent(parent, 0)] == n;
    }
 
    static public void Main()
    {
        List<int> nums = new List<int>{ 4, 3, 12, 8 };
        // Check if it is possible to traverse all pairs
        bool result = CanTraverseAllPairs(nums);
        // Displaying the result
        if (result) {
            Console.WriteLine(1);
        }
        else {
            Console.WriteLine(0);
        }
    }
}


Javascript




// javaScript code for the above approach
 
function findParent(parent, node) {
    return parent[node] === node ? node : (parent[node] = findParent(parent, parent[node]));
}
 
function uniteSets(parent, size, node1, node2) {
    node1 = findParent(parent, node1);
    node2 = findParent(parent, node2);
    if (node1 === node2) {
        return;
    }
    if (size[node1] < size[node2]) {
        [node1, node2] = [node2, node1];
    }
    parent[node2] = node1;
    size[node1] += size[node2];
}
 
function canTraverseAllPairs(nums) {
    const n = nums.length;
    if (n === 1) {
        return true;
    }
    const parent = new Array(n);
    const size = new Array(n);
    for (let i = 0; i < n; ++i) {
        parent[i] = i;
        size[i] = 1;
    }
    const factorsMap = new Map();
    for (let i = 0; i < n; ++i) {
        let x = nums[i];
        if (x === 1) {
            return false;
        }
        for (let factor = 2; factor * factor <= x; ++factor) {
            if (x % factor === 0) {
                if (factorsMap.has(factor)) {
                    uniteSets(parent, size, i, factorsMap.get(factor));
                } else {
                    factorsMap.set(factor, i);
                }
                while (x % factor === 0) {
                    x /= factor;
                }
            }
        }
        if (x > 1) {
            if (factorsMap.has(x)) {
                uniteSets(parent, size, i, factorsMap.get(x));
            } else {
                factorsMap.set(x, i);
            }
        }
    }
    return size[findParent(parent, 0)] === n;
}
 
const nums = [4, 3, 12, 8];
// Check if it is possible to traverse all pairs
const result = canTraverseAllPairs(nums);
// Displaying the result
if(result) {
    console.log(1);
}
else {
    console.log(0)
}


Output

1






Time complexity: O(sqrt(M) * N) where M is the largest number
Auxiliary space: O(N)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads