Open songyy5517 opened 1 year ago
思路1:动态规划,根据已有丑数生成新的丑数
复杂度分析:
import java.util.*;
public class Solution {
public int GetUglyNumber_Solution (int index) {
// 1. 异常处理
if (index < 1)
return 0;
// 2. 状态定义 & 初始化
int[] ugly = new int[index];
ugly[0] = 1;
int idx_2 = 0, idx_3 = 0, idx_5 = 0; // 2, 3, 5分别要乘的丑数索引
// 3. 自底向上生成丑数
for (int i = 1; i < index; i++) {
int prod2 = ugly[idx_2] * 2;
int prod3 = ugly[idx_3] * 3;
int prod5 = ugly[idx_5] * 5;
if (prod2 <= prod3 && prod2 <= prod5) {
ugly[i] = prod2;
idx_2 ++;
}
if (prod3 <= prod2 && prod3 <= prod5) {
ugly[i] = prod3;
idx_3 ++;
}
if (prod5 <= prod3 && prod5 <= prod2) {
ugly[i] = prod5;
idx_5 ++;
}
}
return ugly[index - 1];
}
}
思路2:最小堆 & 哈希表
复杂度分析
Key
import java.util.*;
public class Solution {
public int GetUglyNumber_Solution (int index) {
// 1. 异常处理
if (index < 1)
return 0;
// 2. 定义相关变量:最小堆,哈希表
PriorityQueue<Long> min_Heap = new PriorityQueue(); //存放丑数
HashMap<Long, Boolean> uglies = new HashMap(); // 检查元素是否重复
min_Heap.add((long)1);
uglies.put((long)1, true);
long ugly = 1;
for (int i = 0; i < index; i++){
// 当前最小丑数
ugly = min_Heap.remove();
// 加入新的丑数
for (int j : new int[]{2, 3, 5}){
long ugly_j = ugly * j;
if (!uglies.containsKey(ugly_j)){
min_Heap.add(ugly_j);
uglies.put(ugly_j, true);
}
}
}
return (int)ugly;
}
}
2023/3/28 2023/12/6 2024/1/18
2024/4/6
我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。
示例:
分析 由题可知,我们需要求得第n个丑数。我们需要解决的问题包括两部分,一是求解各个丑数,二是保证求得的丑数升序排列。丑数有一个很重要的性质:一个丑数乘2,3,5之后还是丑数。因此,我们可以从第一个丑数1出发,分别乘2,3,5自底向上求出之后的丑数。为了保证丑数升序排列,我们可以为2,3,5分别设置三个待乘丑数索引,将索引所在的丑数分别乘2,3,5即可得到三个备选的新丑数,其中的最小值即为最后的新丑数(动态规划)。此外,我们还可以使用最小堆来保存丑数,因为最小堆的堆顶元素总是为最小值,所以我们可以将生成的丑数依次加入最小堆,再从堆中取出元素即可保证顺序。