https://leetcode.com/problems/gcd-sort-of-an-array/
方法还是很巧妙的,也很考验编程的基本功,记下来备忘。


个人题解

  1. func gcdSort(nums []int) bool {
  2. set := make(map[int]int)
  3. for _, x := range(nums) {
  4. // 遍历所有x的primeFactor,union起来
  5. xx := x
  6. for p := 2; p * p <= xx; p++ {
  7. if xx % p == 0 {
  8. setUnion(set, x, p)
  9. for xx % p == 0 {
  10. xx /= p
  11. }
  12. }
  13. }
  14. // x是素数的情况下,其本身也是primeFactor
  15. if xx != 1 {
  16. setUnion(set, x, xx)
  17. }
  18. }
  19. sorted := make([]int, len(nums))
  20. copy(sorted, nums)
  21. sort.Ints(sorted)
  22. for i,_ := range(nums) {
  23. r1, r2 := setFind(set, sorted[i]), setFind(set, nums[i])
  24. if r1 != r2 {
  25. return false
  26. }
  27. }
  28. return true
  29. }
  30. func setFind(set map[int]int, x int) int {
  31. if v, ok := set[x]; ok {
  32. if v < 0 {
  33. return x
  34. }
  35. set[x] = setFind(set, v)
  36. return set[x]
  37. } else {
  38. set[x] = -1
  39. return x
  40. }
  41. }
  42. func setUnion(set map[int]int, x int, y int) {
  43. rx := setFind(set, x)
  44. ry := setFind(set, y)
  45. if rx == ry {
  46. return
  47. }
  48. if set[rx] < set[ry] {
  49. set[rx] += set[ry]
  50. set[ry] = rx
  51. } else {
  52. set[ry] += set[rx]
  53. set[rx] = ry
  54. }
  55. }

题目分析

这道题的其中一个考点,并查集,应该比较容易想到,只有当前的元素和目标的元素(排序好之后对应的元素)能够互换,才能够打到最终的目标。
那么问题转化为,union的条件是什么呢?题目中给的很直接,两个数不互质。
可是两两计算GCD,用辗转相除法,复杂度太高,这就太难办了。

那么可以找一个中间量,就是每个数的primeFactors,每个数和其所有的primeFactors都可以union,如此通过primeFactors作为桥梁,不互质的数也都union了起来,妙呀妙呀。

具体的优雅实现可能还需要一些trick,直接看代码吧。