leetcode

来源:互联网 发布:阿里云app名师课堂 编辑:程序博客网 时间:2024/06/07 02:29

算法系列博客之Dynamic Programming

本篇博客将运用动态规划的思想来解决leetcode上264号问题


问题描述:

Write a program to find the n-th ugly number.
Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. For example, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers.
Note that 1 is typically treated as an ugly number, and n does not exceed 1690.

特意挑出此题发博的原因在于它较之前所写DP问题有明显两处不同
      状态转移不依赖于一个给定的特征列表
      如果把每个丑数视为一个状态,则它并不是简单的依赖于固定前一项或者前几项

根据基本的合数的质因数分解可以明白这样一个简单的道理
仅需要将前面的丑数简单的乘以2/3/5即可构造出后面的丑数
关键在于丑数的选择以及2/3/5的选择,得出的结果还要做到不重不漏

事实上,考虑它只能通过乘以2/3/5,且每个数最多只能把这三个数各乘一次
问题就可以看作,新的状态依赖于前面的某三个状态,并且这三个状态都一定会顺次后移
不妨用三个数state[3]来记录2/3/5分别对应依赖于哪三个状态
然后用这三个状态构造出三个丑数(即三个新状态),选择最小的,并将其对应状态顺移

显然5对应状态一定是最靠前的,再前面的状态无需保留
其次还需注意可能两个或者三个状态构造出的三个新状态都相同,这种情况三个状态都应该顺移
至此,可以很清晰的实现代码逻辑结构如下

class Solution(object):    def nthUglyNumber(self, n):        if n < 4: return n        cur = 3        state = [1, 1, 0]        numsqueue = [1, 2, 3]        while cur < n:            new1 = numsqueue[state[0]] * 2            new2 = numsqueue[state[1]] * 3            new3 = numsqueue[0] * 5            newnum = min(min(new1, new2), new3)            if newnum == new1:                state[0] += 1            if newnum == new2:                state[1] += 1            if newnum == new3:                numsqueue.pop(0)                state[0] -= 1                state[1] -= 1            numsqueue.append(newnum)            cur += 1        return numsqueue[-1]

时间复杂度分析,整个算法只需要n次循环,每次循环执行常数条指令,因而O(n)
空间复杂度分析,使用了一个变量一个3元素列表和一个变长列表,而变长列表规模分析起来比较困难,但一定不会超过n,因而不妨简单归为O(n), 它也仍然是一个高效的算法

原创粉丝点击