丑数(Ugly Numbers)是指其质因数只包含 2、3 和 5 的正整数。换句话说,丑数是可以表示为 2a×3b×5c2^a \times 3^b \times 5^c2a×3b×5c 形式的数,其中 aaa、bbb 和 ccc 是非负整数。第一个丑数是 1(通常认为 1 是丑数)
下面的是python实现
def generate_ugly_numbers(n):
if n <= 0:
return []
ugly_numbers = [1]
i2 = i3 = i5 = 0
for _ in range(1, n):
next_ugly_2 = ugly_numbers[i2] * 2
next_ugly_3 = ugly_numbers[i3] * 3
next_ugly_5 = ugly_numbers[i5] * 5
next_ugly = min(next_ugly_2, next_ugly_3, next_ugly_5)
ugly_numbers.append(next_ugly)
if next_ugly == next_ugly_2:
i2 += 1
if next_ugly == next_ugly_3:
i3 += 1
if next_ugly == next_ugly_5:
i5 += 1
return ugly_numbers
# 示例:获取前10个丑数
ugly_numbers = generate_ugly_numbers(10)
print(ugly_numbers)
下面的是用cpp实现
#include <iostream>
#include <vector>
#include <algorithm> // for std::min
std::vector<int> generateUglyNumbers(int n) {
if (n <= 0) {
return {};
}
std::vector<int> uglyNumbers(n);
uglyNumbers[0] = 1; // 第一个丑数是1
int i2 = 0, i3 = 0, i5 = 0; // 分别指向将乘以2、3、5的下一个丑数
for (int i = 1; i < n; ++i) {
int nextUgly2 = uglyNumbers[i2] * 2;
int nextUgly3 = uglyNumbers[i3] * 3;
int nextUgly5 = uglyNumbers[i5] * 5;
int nextUgly = std::min({nextUgly2, nextUgly3, nextUgly5});
uglyNumbers[i] = nextUgly;
if (nextUgly == nextUgly2) {
++i2;
}
if (nextUgly == nextUgly3) {
++i3;
}
if (nextUgly == nextUgly5) {
++i5;
}
}
return uglyNumbers;
}
int main() {
int n = 10; // 可以更改n的值来获取前n个丑数
std::vector<int> uglyNumbers = generateUglyNumbers(n);
// 输出前n个丑数
for (int num : uglyNumbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
具体变化过程
假设我们要生成前 n = 10
个丑数,初始时 uglyNumbers
中已经存储了第一个丑数1(uglyNumbers[0] = 1
),指针 i2 = 0, i3 = 0, i5 = 0
。
-
第2个丑数:
- 计算
nextUgly2 = uglyNumbers[i2] * 2 = 1 * 2 = 2
- 计算
nextUgly3 = uglyNumbers[i3] * 3 = 1 * 3 = 3
- 计算
nextUgly5 = uglyNumbers[i5] * 5 = 1 * 5 = 5
- 最小值是
2
,因此确定第二个丑数为2
。将i2
增加1,i2 = 1
。
- 计算
-
第3个丑数:
- 计算
nextUgly2 = uglyNumbers[i2] * 2 = 2 * 2 = 4
- 计算
nextUgly3 = uglyNumbers[i3] * 3 = 1 * 3 = 3
- 计算
nextUgly5 = uglyNumbers[i5] * 5 = 1 * 5 = 5
- 最小值是
3
,因此确定第三个丑数为3
。将i3
增加1,i3 = 1
。
- 计算
-
第4个丑数:
- 计算
nextUgly2 = uglyNumbers[i2] * 2 = 2 * 2 = 4
- 计算
nextUgly3 = uglyNumbers[i3] * 3 = 2 * 3 = 6
- 计算
nextUgly5 = uglyNumbers[i5] * 5 = 1 * 5 = 5
- 最小值是
4
,因此确定第四个丑数为4
。将i2
增加1,i2 = 2
。
- 计算
-
第5个丑数:
- 计算
nextUgly2 = uglyNumbers[i2] * 2 = 3 * 2 = 6
- 计算
nextUgly3 = uglyNumbers[i3] * 3 = 2 * 3 = 6
- 计算
nextUgly5 = uglyNumbers[i5] * 5 = 1 * 5 = 5
- 最小值是
5
,因此确定第五个丑数为5
。将i5
增加1,i5 = 1
。
- 计算
-
第6个丑数:
- 计算
nextUgly2 = uglyNumbers[i2] * 2 = 3 * 2 = 6
- 计算
nextUgly3 = uglyNumbers[i3] * 3 = 2 * 3 = 6
- 计算
nextUgly5 = uglyNumbers[i5] * 5 = 2 * 5 = 10
- 最小值是
6
,因此确定第六个丑数为6
。同时更新i2
和i3
,i2 = 3
,i3 = 2
。
- 计算
-
第7个丑数:
- 计算
nextUgly2 = uglyNumbers[i2] * 2 = 4 * 2 = 8
- 计算
nextUgly3 = uglyNumbers[i3] * 3 = 3 * 3 = 9
- 计算
nextUgly5 = uglyNumbers[i5] * 5 = 2 * 5 = 10
- 最小值是
8
,因此确定第七个丑数为8
。将i2
增加1,i2 = 4
。
- 计算
-
第8个丑数:
- 计算
nextUgly2 = uglyNumbers[i2] * 2 = 5 * 2 = 10
- 计算
nextUgly3 = uglyNumbers[i3] * 3 = 3 * 3 = 9
- 计算
nextUgly5 = uglyNumbers[i5] * 5 = 2 * 5 = 10
- 最小值是
9
,因此确定第八个丑数为9
。将i3
增加1,i3 = 3
。
- 计算
-
第9个丑数:
- 计算
nextUgly2 = uglyNumbers[i2] * 2 = 5 * 2 = 10
- 计算
nextUgly3 = uglyNumbers[i3] * 3 = 4 * 3 = 12
- 计算
nextUgly5 = uglyNumbers[i5] * 5 = 2 * 5 = 10
- 最小值是
10
,因此确定第九个丑数为10
。同时更新i2
和i5
,i2 = 5
,i5 = 2
。
- 计算
-
第10个丑数:
- 计算
nextUgly2 = uglyNumbers[i2] * 2 = 6 * 2 = 12
- 计算
nextUgly3 = uglyNumbers[i3] * 3 = 4 * 3 = 12
- 计算
nextUgly5 = uglyNumbers[i5] * 5 = 3 * 5 = 15
- 最小值是
12
,因此确定第十个丑数为12
。同时更新i2
和i3
,i2 = 6
,i3 = 4
。
- 计算
通过这种方式,指针 i2
、i3
和 i5
在数组 uglyNumbers
中不断向前推进,确保每次选出最小的可能丑数,避免重复计算,并生成有序的丑数序列。