https://leetcode.com/problems/gcd-sort-of-an-array/
方法还是很巧妙的,也很考验编程的基本功,记下来备忘。
个人题解
func gcdSort(nums []int) bool {
set := make(map[int]int)
for _, x := range(nums) {
// 遍历所有x的primeFactor,union起来
xx := x
for p := 2; p * p <= xx; p++ {
if xx % p == 0 {
setUnion(set, x, p)
for xx % p == 0 {
xx /= p
}
}
}
// x是素数的情况下,其本身也是primeFactor
if xx != 1 {
setUnion(set, x, xx)
}
}
sorted := make([]int, len(nums))
copy(sorted, nums)
sort.Ints(sorted)
for i,_ := range(nums) {
r1, r2 := setFind(set, sorted[i]), setFind(set, nums[i])
if r1 != r2 {
return false
}
}
return true
}
func setFind(set map[int]int, x int) int {
if v, ok := set[x]; ok {
if v < 0 {
return x
}
set[x] = setFind(set, v)
return set[x]
} else {
set[x] = -1
return x
}
}
func setUnion(set map[int]int, x int, y int) {
rx := setFind(set, x)
ry := setFind(set, y)
if rx == ry {
return
}
if set[rx] < set[ry] {
set[rx] += set[ry]
set[ry] = rx
} else {
set[ry] += set[rx]
set[rx] = ry
}
}
题目分析
这道题的其中一个考点,并查集,应该比较容易想到,只有当前的元素和目标的元素(排序好之后对应的元素)能够互换,才能够打到最终的目标。
那么问题转化为,union的条件是什么呢?题目中给的很直接,两个数不互质。
可是两两计算GCD,用辗转相除法,复杂度太高,这就太难办了。
那么可以找一个中间量,就是每个数的primeFactors,每个数和其所有的primeFactors都可以union,如此通过primeFactors作为桥梁,不互质的数也都union了起来,妙呀妙呀。
具体的优雅实现可能还需要一些trick,直接看代码吧。