- 操作系统:ubuntu22.04
- IDE:Visual Studio Code
- 编程语言:C++11
题目描述
我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。例如 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。
请编写一个函数,找出第 n 个丑数。
示例:
输入: n = 10
输出: 12
解释: 第10个丑数是12
解法思路:动态规划 + 三指针
这是一道典型的动态规划问题,也可以用最小堆来解,但最优解是使用 三指针法,时间复杂度为 O(n),空间复杂度为 O(n)。
思路详解:
我们要构造一个丑数数组 dp[],其中 dp[i] 表示第 i 个丑数。
每个新的丑数只能由之前的丑数乘以 2、3 或 5 得到。
我们维护三个指针:
- i2:指向下一个将乘以 2 的位置;
- i3:指向下一个将乘以 3 的位置;
- i5:指向下一个将乘以 5 的位置;
每次取这三个候选值中的最小值作为下一个丑数,并移动对应指针
代码实现
#include <vector>
using namespace std;
class Solution {
public:
int nthUglyNumber( int n )
{
vector< int > dp( n );
dp[ 0 ] = 1; // 第一个丑数是1
int i2 = 0, i3 = 0, i5 = 0;
for ( int i = 1; i < n; ++i )
{
int next2 = dp[ i2 ] * 2;
int next3 = dp[ i3 ] * 3;
int next5 = dp[ i5 ] * 5;
int nextUgly = min( next2, min( next3, next5 ) );
dp[ i ] = nextUgly;
if ( nextUgly == next2 )
i2++;
if ( nextUgly == next3 )
i3++;
if ( nextUgly == next5 )
i5++;
}
return dp[ n - 1 ];
}
};
#include <iostream>
int main()
{
Solution sol;
cout <<"第10个丑数:"<< sol.nthUglyNumber( 10 ) << endl; // 输出 12
cout <<"第1个丑数:"<< sol.nthUglyNumber( 1 ) << endl; // 输出 1
cout << "第15个丑数:"<<sol.nthUglyNumber( 15 ) << endl; // 输出 24
return 0;
}
运行结果
第10个丑数:12
第1个丑数:1
第15个丑数:24