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:
#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;
}
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);
}
}
}
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()
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 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)