原题链接:
http://www.lintcode.com/zh-cn/problem/ugly-number-ii/
题目描述
设计一个算法,找出只含素因子2,3,5 的第 n 小的数。
符合条件的数如:1, 2, 3, 4, 5, 6, 8, 9, 10, 12...
注意事项
我们可以认为1也是一个丑数
样例
如果n = 9, 返回 10
题目解析:
题目给出了丑数的定义,是想要我们用一个算法找出丑数。
思路
思路一
一个比较简单的思路是,从小到大遍历整数,然后判断该数是不是丑数。 问题就在于,如何判断该数是不是丑数? 根据定义,丑数是只含有2,3,5因子的数,也就是说丑数是由m个2,n个3,k个5相乘得到。那么,丑数就一定能被2、3、5中的一个或者多个整除。并且整除下去,直到不能整除为止,最终得出来的结果就一定是1。
值得一说的是,这种方法思路上是没问题的,但是时间过长,程序会报超时。
思路二
直接根据定义来找到丑数,ugly=(m*2)*(n*3)*(k*5)。定义很简单,问题是将得出来的丑数从小到大排列。
这里比较用语言来表达出来。先上代码
ugly2 = uglyList[num_2]*2
ugly3 = uglyList[num_3]*3
ugly5 = uglyList[num_5]*5
ugly = min(ugly2,ugly3,ugly5)
第一个丑数为1,然后第二个丑数就从1*2=2,1*3=3,1*5=5中最小的那个数取得。显然是2.这时,丑数数组就是[1,2]。
然后呢,需要从2*2=4,1*3=3,1*5=5中取最小的那个数3.此时。丑数数组为[1,2,3].
接着,从2*2=4,2*3=6,1*5=5中取最小的4,此时丑数数组为[1,2,3,4]。
接着,从3*2=6,2*3=6,1*5=5中取最小的5.此时丑数数组为[1,2,3,4,5]。
看到规律了吗? 丑数数组中,每个丑数乘以2,乘以3,乘以5得出的新的数都是丑数。那么,我们就将数组中第一个丑数乘以2,只要乘以2的数被选取进了丑数数组,那么就到当前乘以2的那个丑数的下一个丑数乘以2,也就是上面的num_2这个下标+1。乘以3和乘以5都是相似的。最终从得出来的新丑数ugly2,ugly3,ugly5中选取最小的那个丑数放入丑数数组。以此类推。
这里需要注意的是, 有可能ugly2,ugly3,ugly5会相等。所以,需要判断下是否跟这3个数的哪个相等,只要相等,就将其下标+1.
代码(Python)
思路一代码:
"""
@param n: An integer
@return: the nth prime number as description.
"""
def nthUglyNumber(self, n):
# write your code here
if n == 1:
return 1
#第count个丑数
count = 1
#从2遍历到无穷
num = 2
while(count < n):
tempNum = num
#如果能被2整除,那就除2
while(tempNum % 2 == 0):
tempNum = tempNum/2
while(tempNum % 3 == 0):
tempNum = tempNum / 3
while(tempNum % 5 == 0):
tempNum = tempNum / 5
#整除过后,结果为1.代表是丑数
if tempNum == 1:
count += 1
#第n个参数,返回结果
if count == n:
return num
num += 1
思路二代码:
"""
@param n: An integer
@return: the nth prime number as description.
"""
def nthUglyNumber1(self, n):
if n == 1:
return 1
#存放丑数的数组
uglyList = [1]
#当前丑数数组中,当前要乘以2那个丑数在数组中的位置。
#丑数数组中的所有丑数,乘以2之后,都是丑数,所以每个丑数都需要乘以2。
#但是乘以2之后,新的数加入了丑数数组,num_2就要加1,让下一个数乘以2
num_2 = 0
num_3 = 0
num_5 = 0
for i in range(1,n):
ugly2 = uglyList[num_2]*2
ugly3 = uglyList[num_3]*3
ugly5 = uglyList[num_5]*5
#取最小值放入丑数数组
ugly = min(ugly2,ugly3,ugly5)
#print "ugly =",ugly
uglyList.append(ugly)
#如果新的丑数是由乘以2、或者3、或5得来,那么需要将对应的下标加1
#注意这里有可能会出现ugly与其中两个数都相等的情况
if ugly == ugly2:
num_2 += 1
if ugly == ugly3:
num_3 += 1
if ugly == ugly5:
num_5 += 1
#print "uglyList=",uglyList
return uglyList[-1]
谦言忘语
个人目前只懂一丁点python语法,所以不做语法上的优化,而且整体代码风格效果会尽量跟C语言趋于一致。