...
不使用 map 去重 - 而是使用合并 k 个有序链表(丑数 II)的思路
Code Block |
---|
|
func nthSuperUglyNumber(n int, primes []int) int {
h_ := make(Heap, 0, n)
h := &h_
for _, p := range primes {
heap.Push(h, [3]int{1, p, 0})
}
uglys := make([]int, 1, n)
uglys[0] = 1
for len(uglys) < n {
top := heap.Pop(h).([3]int)
num, p, pi := top[0], top[1], top[2]
if num != uglys[len(uglys) - 1] {
uglys = append(uglys, num)
}
heap.Push(h, [3]int{p * uglys[pi], p, pi+1})
}
return uglys[n-1]
}
type Heap [][3]int
func (h Heap) Len() int { return len(h) }
func (h Heap) Less(i, j int) bool { return h[i][0] < h[j][0] }
func (h Heap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *Heap) Push(x any) {
*h = append(*h, x.([3]int))
}
func (h *Heap) Pop() any {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
|
...
Code Block |
---|
|
func nthUglyNumber(n int, a int, b int, c int) int {
h := &Heap{}
heap.Push(h, [2]int{a, a})
heap.Push(h, [2]int{b, b})
heap.Push(h, [2]int{c, c})
i := 0
num := 0
for i < n {
top := heap.Pop(h).([2]int)
v, factor := top[0], top[1]
if v != num {
num = v
i++
}
heap.Push(h, [2]int{v + factor, factor})
}
return num
}
type Heap [][2]int
func (h Heap) Len() int { return len(h) }
func (h Heap) Less(i, j int) bool { return h[i][0] < h[j][0] }
func (h Heap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *Heap) Push(x any) {
*h = append(*h, x.([2]int))
}
func (h *Heap) Pop() any {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
} |
二分 + 集合解法
Code Block |
---|
|
func nthUglyNumber(n int, a int, b int, c int) int {
L, R := 1, int(2e9) + 1
// 二分:找到 [L, R) 范围内满足 f() == n 的最小值
for L < R {
mid := L + (R - L) / 2
if f(mid, a, b, c) >= n {
R = mid
} else { // <
L = mid + 1
}
}
return R
}
func f(num int, a, b, c int) int {
setA := num / a
setB := num / b
setC := num / c
lcmAB := lcm(a, b)
setAB := num / lcmAB
setAC := num / lcm(a, c)
setBC := num / lcm(b, c)
setABC := num / lcm(lcmAB, c)
return setA + setB + setC - setAB - setAC - setBC + setABC
}
func lcm(a, b int) int {
return a * b / gcd(a, b)
}
func gcd(a, b int) int {
// assert a <= b
if a > b { a, b = b, a }
for a != 0 {
a, b = b % a, a
}
return b
} |