Skip to content

Commit 532cf96

Browse files
committed
feat: add solutions to lc problem: No.0313
No.0313.Super Ugly Number
1 parent 91963bf commit 532cf96

File tree

12 files changed

+279
-91
lines changed

12 files changed

+279
-91
lines changed

solution/0300-0399/0313.Super Ugly Number/README.md

Lines changed: 102 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,15 @@
5151

5252
<!-- 这里可写通用的实现逻辑 -->
5353

54-
**方法一:优先队列**
54+
**方法一:优先队列(小根堆)**
5555

56-
根据题目要求,模拟第 1 ~ n 个丑数,显然任意一个丑数 `ugly[i]` 乘以 `primes` 数组中的质数 `primes[i]` 仍旧是丑数。已知 `ugly[1]=1``ugly[2] = min(ugly[1]*primes[i])`,则 `ugly[3]` 应该等于集合 `ugly[2]*primes[i], ugly[1]*primes[i]` 中排除 `ugly[2]` 之后的最小值,依次类推可以得到 `ugly[n]` 的值。
56+
我们用一个优先队列(小根堆)维护所有可能的超级丑数,初始时将 $1$ 放入队列中。
57+
58+
每次从队列中取出最小的超级丑数 $x$,将 $x$ 乘以数组 `primes` 中的每个数,将乘积放入队列中,然后重复上述操作 $n$ 次即可得到第 $n$ 个超级丑数。
59+
60+
由于题目保证第 $n$ 个超级丑数在 $32$ 位带符号整数范围内,因此,我们将乘积放入队列之前,可以先判断乘积是否超过 $2^{31} - 1$,如果超过,则不需要将乘积放入队列中。另外,可以使用欧拉筛优化。
61+
62+
时间复杂度 $O(n \times m \times \log (n \times m))$,空间复杂度 $O(n \times m)$。其中 $m$ 和 $n$ 分别为数组 `primes` 的长度和给定的整数 $n$。
5763

5864
<!-- tabs:start -->
5965

@@ -62,29 +68,107 @@
6268
<!-- 这里可写当前语言的特殊实现逻辑 -->
6369

6470
```python
65-
from queue import PriorityQueue
66-
67-
6871
class Solution:
6972
def nthSuperUglyNumber(self, n: int, primes: List[int]) -> int:
70-
ugly, pq, p = [0]*(n+1), PriorityQueue(), 2
71-
ugly[1] = 1
72-
for prime in primes:
73-
pq.put([prime, prime, 2])
74-
75-
while p <= n:
76-
top = pq.get()
77-
if top[0] != ugly[p-1]:
78-
ugly[p], p = top[0], p+1
79-
top[0], top[2] = ugly[top[2]]*top[1], top[2]+1
80-
pq.put(top)
81-
return ugly[n]
73+
q = [1]
74+
x = 0
75+
mx = (1 << 31) - 1
76+
for _ in range(n):
77+
x = heappop(q)
78+
for k in primes:
79+
if x <= mx // k:
80+
heappush(q, k * x)
81+
if x % k == 0:
82+
break
83+
return x
8284
```
8385

84-
### **Go**
86+
### **Java**
8587

8688
<!-- 这里可写当前语言的特殊实现逻辑 -->
8789

90+
```java
91+
class Solution {
92+
public int nthSuperUglyNumber(int n, int[] primes) {
93+
PriorityQueue<Integer> q = new PriorityQueue<>();
94+
q.offer(1);
95+
int x = 0;
96+
while (n-- > 0) {
97+
x = q.poll();
98+
while (!q.isEmpty() && q.peek() == x) {
99+
q.poll();
100+
}
101+
for (int k : primes) {
102+
if (k <= Integer.MAX_VALUE / x) {
103+
q.offer(k * x);
104+
}
105+
if (x % k == 0) {
106+
break;
107+
}
108+
}
109+
}
110+
return x;
111+
}
112+
}
113+
```
114+
115+
### **C++**
116+
117+
```cpp
118+
class Solution {
119+
public:
120+
int nthSuperUglyNumber(int n, vector<int>& primes) {
121+
priority_queue<int, vector<int>, greater<int>> q;
122+
q.push(1);
123+
int x = 0;
124+
while (n--) {
125+
x = q.top();
126+
q.pop();
127+
for (int& k : primes) {
128+
if (x <= INT_MAX / k) {
129+
q.push(k * x);
130+
}
131+
if (x % k == 0) {
132+
break;
133+
}
134+
}
135+
}
136+
return x;
137+
}
138+
};
139+
```
140+
141+
### **Go**
142+
143+
```go
144+
func nthSuperUglyNumber(n int, primes []int) (x int) {
145+
q := hp{[]int{1}}
146+
for n > 0 {
147+
n--
148+
x = heap.Pop(&q).(int)
149+
for _, k := range primes {
150+
if x <= math.MaxInt32/k {
151+
heap.Push(&q, k*x)
152+
}
153+
if x%k == 0 {
154+
break
155+
}
156+
}
157+
}
158+
return
159+
}
160+
161+
type hp struct{ sort.IntSlice }
162+
163+
func (h *hp) Push(v interface{}) { h.IntSlice = append(h.IntSlice, v.(int)) }
164+
func (h *hp) Pop() interface{} {
165+
a := h.IntSlice
166+
v := a[len(a)-1]
167+
h.IntSlice = a[:len(a)-1]
168+
return v
169+
}
170+
```
171+
88172
```go
89173
type Ugly struct{ value, prime, index int }
90174
type Queue []Ugly

solution/0300-0399/0313.Super Ugly Number/README_EN.md

Lines changed: 93 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,27 +47,105 @@ Priority Queue.
4747
### **Python3**
4848

4949
```python
50-
from queue import PriorityQueue
51-
52-
5350
class Solution:
5451
def nthSuperUglyNumber(self, n: int, primes: List[int]) -> int:
55-
ugly, pq, p = [0]*(n+1), PriorityQueue(), 2
56-
ugly[1] = 1
57-
for prime in primes:
58-
pq.put([prime, prime, 2])
59-
60-
while p <= n:
61-
top = pq.get()
62-
if top[0] != ugly[p-1]:
63-
ugly[p], p = top[0], p+1
64-
top[0], top[2] = ugly[top[2]]*top[1], top[2]+1
65-
pq.put(top)
66-
return ugly[n]
52+
q = [1]
53+
x = 0
54+
mx = (1 << 31) - 1
55+
for _ in range(n):
56+
x = heappop(q)
57+
for k in primes:
58+
if x <= mx // k:
59+
heappush(q, k * x)
60+
if x % k == 0:
61+
break
62+
return x
63+
```
64+
65+
### **Java**
66+
67+
```java
68+
class Solution {
69+
public int nthSuperUglyNumber(int n, int[] primes) {
70+
PriorityQueue<Integer> q = new PriorityQueue<>();
71+
q.offer(1);
72+
int x = 0;
73+
while (n-- > 0) {
74+
x = q.poll();
75+
while (!q.isEmpty() && q.peek() == x) {
76+
q.poll();
77+
}
78+
for (int k : primes) {
79+
if (k <= Integer.MAX_VALUE / x) {
80+
q.offer(k * x);
81+
}
82+
if (x % k == 0) {
83+
break;
84+
}
85+
}
86+
}
87+
return x;
88+
}
89+
}
90+
```
91+
92+
### **C++**
93+
94+
```cpp
95+
class Solution {
96+
public:
97+
int nthSuperUglyNumber(int n, vector<int>& primes) {
98+
priority_queue<int, vector<int>, greater<int>> q;
99+
q.push(1);
100+
int x = 0;
101+
while (n--) {
102+
x = q.top();
103+
q.pop();
104+
for (int& k : primes) {
105+
if (x <= INT_MAX / k) {
106+
q.push(k * x);
107+
}
108+
if (x % k == 0) {
109+
break;
110+
}
111+
}
112+
}
113+
return x;
114+
}
115+
};
67116
```
68117
69118
### **Go**
70119
120+
```go
121+
func nthSuperUglyNumber(n int, primes []int) (x int) {
122+
q := hp{[]int{1}}
123+
for n > 0 {
124+
n--
125+
x = heap.Pop(&q).(int)
126+
for _, k := range primes {
127+
if x <= math.MaxInt32/k {
128+
heap.Push(&q, k*x)
129+
}
130+
if x%k == 0 {
131+
break
132+
}
133+
}
134+
}
135+
return
136+
}
137+
138+
type hp struct{ sort.IntSlice }
139+
140+
func (h *hp) Push(v interface{}) { h.IntSlice = append(h.IntSlice, v.(int)) }
141+
func (h *hp) Pop() interface{} {
142+
a := h.IntSlice
143+
v := a[len(a)-1]
144+
h.IntSlice = a[:len(a)-1]
145+
return v
146+
}
147+
```
148+
71149
```go
72150
type Ugly struct{ value, prime, index int }
73151
type Queue []Ugly
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
class Solution {
2+
public:
3+
int nthSuperUglyNumber(int n, vector<int>& primes) {
4+
priority_queue<int, vector<int>, greater<int>> q;
5+
q.push(1);
6+
int x = 0;
7+
while (n--) {
8+
x = q.top();
9+
q.pop();
10+
for (int& k : primes) {
11+
if (x <= INT_MAX / k) {
12+
q.push(k * x);
13+
}
14+
if (x % k == 0) {
15+
break;
16+
}
17+
}
18+
}
19+
return x;
20+
}
21+
};
Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,26 @@
1-
type Ugly struct{ value, prime, index int }
2-
type Queue []Ugly
3-
4-
func (u Queue) Len() int { return len(u) }
5-
func (u Queue) Swap(i, j int) { u[i], u[j] = u[j], u[i] }
6-
func (u Queue) Less(i, j int) bool { return u[i].value < u[j].value }
7-
func (u *Queue) Push(v interface{}) { *u = append(*u, v.(Ugly)) }
8-
func (u *Queue) Pop() interface{} {
9-
old, x := *u, (*u)[len(*u)-1]
10-
*u = old[:len(old)-1]
11-
return x
12-
}
13-
14-
func nthSuperUglyNumber(n int, primes []int) int {
15-
ugly, pq, p := make([]int, n+1), &Queue{}, 2
16-
ugly[1] = 1
17-
heap.Init(pq)
18-
for _, v := range primes {
19-
heap.Push(pq, Ugly{value: v, prime: v, index: 2})
20-
}
21-
for p <= n {
22-
top := heap.Pop(pq).(Ugly)
23-
if ugly[p-1] != top.value {
24-
ugly[p], p = top.value, p+1
1+
func nthSuperUglyNumber(n int, primes []int) (x int) {
2+
q := hp{[]int{1}}
3+
for n > 0 {
4+
n--
5+
x = heap.Pop(&q).(int)
6+
for _, k := range primes {
7+
if x <= math.MaxInt32/k {
8+
heap.Push(&q, k*x)
9+
}
10+
if x%k == 0 {
11+
break
12+
}
2513
}
26-
top.value, top.index = ugly[top.index]*top.prime, top.index+1
27-
heap.Push(pq, top)
2814
}
29-
return ugly[n]
15+
return
16+
}
17+
18+
type hp struct{ sort.IntSlice }
19+
20+
func (h *hp) Push(v interface{}) { h.IntSlice = append(h.IntSlice, v.(int)) }
21+
func (h *hp) Pop() interface{} {
22+
a := h.IntSlice
23+
v := a[len(a)-1]
24+
h.IntSlice = a[:len(a)-1]
25+
return v
3026
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
class Solution {
2+
public int nthSuperUglyNumber(int n, int[] primes) {
3+
PriorityQueue<Integer> q = new PriorityQueue<>();
4+
q.offer(1);
5+
int x = 0;
6+
while (n-- > 0) {
7+
x = q.poll();
8+
while (!q.isEmpty() && q.peek() == x) {
9+
q.poll();
10+
}
11+
for (int k : primes) {
12+
if (k <= Integer.MAX_VALUE / x) {
13+
q.offer(k * x);
14+
}
15+
if (x % k == 0) {
16+
break;
17+
}
18+
}
19+
}
20+
return x;
21+
}
22+
}
Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
1-
from queue import PriorityQueue
2-
3-
41
class Solution:
52
def nthSuperUglyNumber(self, n: int, primes: List[int]) -> int:
6-
ugly, pq, p = [0] * (n + 1), PriorityQueue(), 2
7-
ugly[1] = 1
8-
for prime in primes:
9-
pq.put([prime, prime, 2])
10-
11-
while p <= n:
12-
top = pq.get()
13-
if top[0] != ugly[p - 1]:
14-
ugly[p], p = top[0], p + 1
15-
top[0], top[2] = ugly[top[2]] * top[1], top[2] + 1
16-
pq.put(top)
17-
return ugly[n]
3+
q = [1]
4+
x = 0
5+
mx = (1 << 31) - 1
6+
for _ in range(n):
7+
x = heappop(q)
8+
for k in primes:
9+
if x <= mx // k:
10+
heappush(q, k * x)
11+
if x % k == 0:
12+
break
13+
return x

0 commit comments

Comments
 (0)