LeetCode 264. Ugly Number II--C++,Python解法

本文详细解析了LeetCode上经典题目“丑数”的多种解法,包括使用队列、最小堆、动态规划等方法,并对比了不同算法的时间效率。通过Python和C++代码实例,深入探讨了如何高效寻找第n个只包含2、3、5为质因数的正整数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目地址:Ugly Number II - LeetCode


Write a program to find the n-th ugly number.

Ugly numbers are positive numbers whose prime factors only include 2, 3, 5.

Example:

Input: n = 10
Output: 12
Explanation: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers.

Note:

1 is typically treated as an ugly number.
n does not exceed 1690.


这道题目是经典的求丑数的题目。
比较容易想到的方法是使用队列,然后不断pop,把当前的数乘以2,3,5。
Python解法如下:

class Solution:
    def nthUglyNumber(self, n: int) -> int:
        count = 0
        l = [1]
        for i in range(0, n-1):
            temp = l.pop(0)
            for j in [2,3,5]:
                if j*temp not in l:
                    l.append(j*temp)
            l.sort()
        return l[0]

这个做法的缺点是比较慢,因为每次都要做很多次判断。
用最小堆和set减少判断次数,时间消耗显著减少。

from heapq import heappop, heappush
class Solution:
    def nthUglyNumber(self, n: int) -> int:
        count = 0
        heap = []
        heappush(heap, 1)
        see=set(heap)
        for i in range(0, n-1):
            temp = heappop(heap)
            for j in [2,3,5]:
                if j*temp not in see:
                    see.add(j*temp)
                    heappush(heap, j*temp)
        return heappop(heap)

更快的,不用排序的解法如下:

class Solution:
    def nthUglyNumber(self, n: int) -> int:
        if n == 1:
            return 1
        l1 = [2]
        l2 = [3]
        l3 = [5]
        for i in range(0, n-2):
            temp = min(l1[0], l2[0], l3[0])
            if temp == l1[0]:
                l1.pop(0)
                l1.append(temp*2)
                l2.append(temp*3)
                l3.append(temp*5)
            elif temp == l2[0]:
                l2.pop(0)
                l2.append(temp*3)
                l3.append(temp*5)
            else:
                l3.pop(0)
                l3.append(temp*5)
        return min(l1[0], l2[0], l3[0])

上面这个解法也有问题,问题是需要pop,而pop操作是比较花费时间的,官方提供的动态规划的解法如下:

class Solution:
    def nthUglyNumber(self, n: int) -> int:
        if n == 1:
            return 1
        nums = [1]
        i2 = i3 = i5 = 0
        for i in range(0, n):
            ugly = min(nums[i2] * 2, nums[i3] * 3, nums[i5] * 5)
            nums.append(ugly)
            if ugly == nums[i2] * 2:
                i2 += 1
            if ugly == nums[i3] * 3:
                i3 += 1
            if ugly == nums[i5] * 5:
                i5 += 1
        return nums[n-1]

C++解法如下:

class Solution {
public:
    int nthUglyNumber(int n) {
        if(n <= 0) return false; // get rid of corner cases 
        if(n == 1) return true; // base case
        int t2 = 0, t3 = 0, t5 = 0; //pointers for 2, 3, 5
        vector<int> k(n);
        k[0] = 1;
        for(int i  = 1; i < n ; i ++)
        {
            k[i] = min(k[t2]*2,min(k[t3]*3,k[t5]*5));
            if(k[i] == k[t2]*2) t2++; 
            if(k[i] == k[t3]*3) t3++;
            if(k[i] == k[t5]*5) t5++;
        }
        return k[n-1];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值