Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Break down a hard problem into reliable checkpoints, edge-case handling, and complexity trade-offs.
You are given an integer array nums, and you can perform the following operation any number of times on nums:
nums[i] and nums[j] if gcd(nums[i], nums[j]) > 1 where gcd(nums[i], nums[j]) is the greatest common divisor of nums[i] and nums[j].Return true if it is possible to sort nums in non-decreasing order using the above swap method, or false otherwise.
Example 1:
Input: nums = [7,21,3] Output: true Explanation: We can sort [7,21,3] by performing the following operations: - Swap 7 and 21 because gcd(7,21) = 7. nums = [21,7,3] - Swap 21 and 3 because gcd(21,3) = 3. nums = [3,7,21]
Example 2:
Input: nums = [5,2,6,2] Output: false Explanation: It is impossible to sort the array because 5 cannot be swapped with any other element.
Example 3:
Input: nums = [10,5,9,3,15] Output: true We can sort [10,5,9,3,15] by performing the following operations: - Swap 10 and 15 because gcd(10,15) = 5. nums = [15,5,9,3,10] - Swap 15 and 3 because gcd(15,3) = 3. nums = [3,5,9,15,10] - Swap 10 and 15 because gcd(10,15) = 5. nums = [3,5,9,10,15]
Constraints:
1 <= nums.length <= 3 * 1042 <= nums[i] <= 105Problem summary: You are given an integer array nums, and you can perform the following operation any number of times on nums: Swap the positions of two elements nums[i] and nums[j] if gcd(nums[i], nums[j]) > 1 where gcd(nums[i], nums[j]) is the greatest common divisor of nums[i] and nums[j]. Return true if it is possible to sort nums in non-decreasing order using the above swap method, or false otherwise.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Math · Union-Find
[7,21,3]
[5,2,6,2]
[10,5,9,3,15]
rank-transform-of-a-matrix)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1998: GCD Sort of an Array
class Solution {
private int[] p;
public boolean gcdSort(int[] nums) {
int n = 100010;
p = new int[n];
Map<Integer, List<Integer>> f = new HashMap<>();
for (int i = 0; i < n; ++i) {
p[i] = i;
}
int mx = 0;
for (int num : nums) {
mx = Math.max(mx, num);
}
for (int i = 2; i <= mx; ++i) {
if (f.containsKey(i)) {
continue;
}
for (int j = i; j <= mx; j += i) {
f.computeIfAbsent(j, k -> new ArrayList<>()).add(i);
}
}
for (int i : nums) {
for (int j : f.get(i)) {
p[find(i)] = find(j);
}
}
int[] s = new int[nums.length];
System.arraycopy(nums, 0, s, 0, nums.length);
Arrays.sort(s);
for (int i = 0; i < nums.length; ++i) {
if (s[i] != nums[i] && find(nums[i]) != find(s[i])) {
return false;
}
}
return true;
}
int find(int x) {
if (p[x] != x) {
p[x] = find(p[x]);
}
return p[x];
}
}
// Accepted solution for LeetCode #1998: GCD Sort of an Array
var p []int
func gcdSort(nums []int) bool {
n := 100010
p = make([]int, n)
for i := 0; i < n; i++ {
p[i] = i
}
mx := 0
for _, num := range nums {
mx = max(mx, num)
}
f := make([][]int, mx+1)
for i := 2; i <= mx; i++ {
if len(f[i]) > 0 {
continue
}
for j := i; j <= mx; j += i {
f[j] = append(f[j], i)
}
}
for _, i := range nums {
for _, j := range f[i] {
p[find(i)] = find(j)
}
}
s := make([]int, len(nums))
for i, num := range nums {
s[i] = num
}
sort.Ints(s)
for i, num := range nums {
if s[i] != num && find(s[i]) != find(num) {
return false
}
}
return true
}
func find(x int) int {
if p[x] != x {
p[x] = find(p[x])
}
return p[x]
}
# Accepted solution for LeetCode #1998: GCD Sort of an Array
class Solution:
def gcdSort(self, nums: List[int]) -> bool:
n = 10**5 + 10
p = list(range(n))
f = defaultdict(list)
mx = max(nums)
for i in range(2, mx + 1):
if f[i]:
continue
for j in range(i, mx + 1, i):
f[j].append(i)
def find(x):
if p[x] != x:
p[x] = find(p[x])
return p[x]
for i in nums:
for j in f[i]:
p[find(i)] = find(j)
s = sorted(nums)
for i, num in enumerate(nums):
if s[i] != num and find(num) != find(s[i]):
return False
return True
// Accepted solution for LeetCode #1998: GCD Sort of an Array
/**
* [1998] GCD Sort of an Array
*
* You are given an integer array nums, and you can perform the following operation any number of times on nums:
*
* Swap the positions of two elements nums[i] and nums[j] if gcd(nums[i], nums[j]) > 1 where gcd(nums[i], nums[j]) is the greatest common divisor of nums[i] and nums[j].
*
* Return true if it is possible to sort nums in non-decreasing order using the above swap method, or false otherwise.
*
* Example 1:
*
* Input: nums = [7,21,3]
* Output: true
* Explanation: We can sort [7,21,3] by performing the following operations:
* - Swap 7 and 21 because gcd(7,21) = 7. nums = [<u>21</u>,<u>7</u>,3]
* - Swap 21 and 3 because gcd(21,3) = 3. nums = [<u>3</u>,7,<u>21</u>]
*
* Example 2:
*
* Input: nums = [5,2,6,2]
* Output: false
* Explanation: It is impossible to sort the array because 5 cannot be swapped with any other element.
*
* Example 3:
*
* Input: nums = [10,5,9,3,15]
* Output: true
* We can sort [10,5,9,3,15] by performing the following operations:
* - Swap 10 and 15 because gcd(10,15) = 5. nums = [<u>15</u>,5,9,3,<u>10</u>]
* - Swap 15 and 3 because gcd(15,3) = 3. nums = [<u>3</u>,5,9,<u>15</u>,10]
* - Swap 10 and 15 because gcd(10,15) = 5. nums = [3,5,9,<u>10</u>,<u>15</u>]
*
*
* Constraints:
*
* 1 <= nums.length <= 3 * 10^4
* 2 <= nums[i] <= 10^5
*
*/
pub struct Solution {}
// problem: https://leetcode.com/problems/gcd-sort-of-an-array/
// discuss: https://leetcode.com/problems/gcd-sort-of-an-array/discuss/?currentPage=1&orderBy=most_votes&query=
// submission codes start here
impl Solution {
pub fn gcd_sort(nums: Vec<i32>) -> bool {
false
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[ignore]
fn test_1998_example_1() {
let nums = vec![7, 21, 3];
let result = true;
assert_eq!(Solution::gcd_sort(nums), result);
}
#[test]
#[ignore]
fn test_1998_example_2() {
let nums = vec![5, 2, 6, 2];
let result = false;
assert_eq!(Solution::gcd_sort(nums), result);
}
#[test]
#[ignore]
fn test_1998_example_3() {
let nums = vec![10, 5, 9, 3, 15];
let result = true;
assert_eq!(Solution::gcd_sort(nums), result);
}
}
// Accepted solution for LeetCode #1998: GCD Sort of an Array
// Auto-generated TypeScript example from java.
function exampleSolution(): void {
}
// Reference (java):
// // Accepted solution for LeetCode #1998: GCD Sort of an Array
// class Solution {
// private int[] p;
//
// public boolean gcdSort(int[] nums) {
// int n = 100010;
// p = new int[n];
// Map<Integer, List<Integer>> f = new HashMap<>();
// for (int i = 0; i < n; ++i) {
// p[i] = i;
// }
// int mx = 0;
// for (int num : nums) {
// mx = Math.max(mx, num);
// }
// for (int i = 2; i <= mx; ++i) {
// if (f.containsKey(i)) {
// continue;
// }
// for (int j = i; j <= mx; j += i) {
// f.computeIfAbsent(j, k -> new ArrayList<>()).add(i);
// }
// }
// for (int i : nums) {
// for (int j : f.get(i)) {
// p[find(i)] = find(j);
// }
// }
// int[] s = new int[nums.length];
// System.arraycopy(nums, 0, s, 0, nums.length);
// Arrays.sort(s);
// for (int i = 0; i < nums.length; ++i) {
// if (s[i] != nums[i] && find(nums[i]) != find(s[i])) {
// return false;
// }
// }
// return true;
// }
//
// int find(int x) {
// if (p[x] != x) {
// p[x] = find(p[x]);
// }
// return p[x];
// }
// }
Use this to step through a reusable interview workflow for this problem.
Track components with a list or adjacency matrix. Each union operation may need to update all n elements’ component labels, giving O(n) per union. For n union operations total: O(n²). Find is O(1) with direct lookup, but union dominates.
With path compression and union by rank, each find/union operation takes O(α(n)) amortized time, where α is the inverse Ackermann function — effectively constant. Space is O(n) for the parent and rank arrays. For m operations on n elements: O(m × α(n)) total.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Wrong move: Temporary multiplications exceed integer bounds.
Usually fails on: Large inputs wrap around unexpectedly.
Fix: Use wider types, modular arithmetic, or rearranged operations.