把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第 n个丑数。
数据范围:
要求:空间复杂度 , 时间复杂度
class Solution: def GetUglyNumber_Solution(self, index): # write code here res = [0]*index x,y,z = 0,0,0 if index <=6: return index n = index res[0] = 1 for i in range(1,n): res[i] = min(2*res[x],min(3*res[y],5*res[z])) if res[i] == 2*res[x]: x+=1 if res[i] == 3*res[y]: y+=1 if res[i] == 5*res[z]: z+=1 return res[index-1]理解算法本身通过题解一开始,两次min()得到res对应位置上的值
# -*- coding:utf-8 -*- class Solution: def GetUglyNumber_Solution(self, index): # write code here if not index: return 0 res = [1] array = [] while len(res) < index: # 丑数一定是前面的丑数乘以2,3,5得到的 for i in [res[-1]*2, res[-1]*3, res[-1]*5]: if i not in array: array.append(i) next_ugly = min(array) res.append(next_ugly) array.remove(next_ugly) return res[-1]
# -*- coding:utf-8 -*- class Solution: def GetUglyNumber_Solution(self, index): # write code here if index<1: return 0 uglynums = [1] ugly_2 = [] ugly_3 = [] ugly_5 = [] for i in range(1,index): ugly_2.append(uglynums[-1]*2) ugly_3.append(uglynums[-1]*3) ugly_5.append(uglynums[-1]*5) min_ugly = min(ugly_2[0],ugly_3[0],ugly_5[0]) uglynums.append(min_ugly) if min_ugly==ugly_2[0]: ugly_2.pop(0) if min_ugly==ugly_3[0]: ugly_3.pop(0) if min_ugly==ugly_5[0]: ugly_5.pop(0) return uglynums[-1]
# -*- coding:utf-8 -*- class Solution: def GetUglyNumber_Solution(self, index): if index <= 1: return index result = [] length, point = 0,1 while length < index: length += 1 result.append(point) temp = point while temp % 5 == 0: temp = temp / 5 while temp % 3 == 0: temp = temp / 3 while temp % 2 == 0: temp = temp / 2 if temp > 5: result.pop() length -= 1 point += 1 return result[index-1]
python解法:
# -*- coding:utf-8 -*- ''' 解法1:动态规划,思想: 丑数*丑数=丑数; 假设当前存在3个数组nums2,nums3,nums5分别代表丑数序列从1开始分别乘以2,3,5的序列,即: nums2 = {1*2, 2*2, 3*2, 4*2, 5*2, 6*2, 8*2...} nums3 = {1*3, 2*3, 3*3, 4*3, 5*3, 6*3, 8*3...} nums5 = {1*5, 2*5, 3*5, 4*5, 5*5, 6*5, 8*5...} 选择最小的n个; ''' class Solution: def GetUglyNumber_Solution(self, index): if index == 0: return 0 dp = [1] * index a,b,c = 0,0,0 for i in range(1,index): # 从dp[1]开始; n2,n3,n5 = dp[a]*2,dp[b]*3,dp[c]*5 dp[i] = min(n2,n3,n5) # 每次选择最小的丑数; if dp[i] == n2: a += 1 if dp[i] == n3: b += 1 if dp[i] == n5: c += 1 # print(dp[i]) return dp[index-1]
# -*- coding:utf-8 -*- class Solution: def GetUglyNumber_Solution(self, index): # write code here if index < 1: return 0 res = [1] t2 = 0 t3 = 0 t5 = 0 while index-1: # 因为index从1开始计数 res.append(min(res[t2]*2, res[t3]*3, res[t5]*5)) while res[t2]*2 <= res[-1]: t2 += 1 while res[t3]*3 <= res[-1]: t3 += 1 while res[t5]*5 <= res[-1]: t5 += 1 index -= 1 return res[-1]
# -*- coding:utf-8 -*- class Solution: def GetUglyNumber_Solution(self, index): # write code here if index<1: return 0 list = [1] twopointer = 0 threepointer = 0 fivepointer = 0 count = 0 while count != index: minValue = min(2*list[twopointer],3*list[threepointer],5*list[fivepointer]) list.append(minValue) count +=1 if minValue == 2*list[twopointer]: twopointer +=1 if minValue == 3*list[threepointer]: threepointer +=1 if minValue == 5*list[fivepointer]: fivepointer +=1 return list[count-1]讲*2、*3、*5的指针开始都指向第一个数,然后比较结果,将最小的依次放入后面。
class Solution: def GetUglyNumber_Solution(self, index): # write code here if index<=0: return 0 l=[1] point_2=0 point_3=0 point_5=0 count=1 while count!=index: l.append(min(2*l[point_2],3*l[point_3],5*l[point_5])) count+=1 if 2*l[point_2]==l[-1]: point_2+=1 if 3*l[point_3]==l[-1]: point_3+=1 if 5*l[point_5]==l[-1]: point_5+=1 return l[-1]
# -*- coding:utf-8 -*- # 只需要把得到的丑数不断地乘以2、3、5之后并放入他们应该放置的位置即可, # 而此题的难点就在于如何有序的放在合适的位置。 # 1乘以 (2、3、5)=2、3、5;2乘以(2、3、5)=4、6、10;3乘以(2、3、5)=6,9,15;5乘以(2、3、5)=10、15、25; # 从这里我们可以看到如果不加策略地添加丑数是会有重复并且无序, # 而在2x,3y,5z中,如果x=y=z那么最小丑数一定是乘以2的,但关键是有可能存在x》y》z的情况, # 所以我们要维持三个指针来记录当前乘以2、乘以3、乘以5的最小值,然后当其被选为新的最小值后,要把相应的指针+1; # 因为这个指针会逐渐遍历整个数组,因此最终数组中的每一个值都会被乘以2、乘以3、乘以5,也就是实现了我们最开始的想法, # 只不过不是同时成乘以2、3、5,而是在需要的时候乘以2、3、5. class Solution: def GetUglyNumber_Solution(self, index): # write code here if index == 1: return 1 res = [1] i2 = 0 i3 = 0 i5 = 0 for i in range(index - 1): m = min(res[i2] * 2, res[i3] * 3, res[i5] * 5) res.append(m) if m % 2 == 0: i2 += 1 if m % 3 == 0: i3 += 1 if m % 5 == 0: i5 += 1 return res[-1]
class Solution: def GetUglyNumber_Solution(self, index): # write code here if index <= 0: return 0 # 储存丑数 ugly_list = [1] # 指针标明这是第几个丑数 pointer = 0 # 乘2 的指针 pointer2 = 0 # 乘3 的指针 pointer3 = 0 # 乘5 的指针 pointer5 = 0 # 直到 第index 个丑数 终止 while pointer < index-1: # 确保 指针指向的是第一个超过丑数的丑数 while 2 * ugly_list[pointer2] <= ugly_list[pointer]: pointer2 += 1 while 3 * ugly_list[pointer3] <= ugly_list[pointer]: pointer3 += 1 while 5 * ugly_list[pointer5] <= ugly_list[pointer]: pointer5 += 1 # 比较哪个丑数最小 就是下一个 next_num = min(2 * ugly_list[pointer2], 3 * ugly_list[pointer3], 5 * ugly_list[pointer5]) # 存上 ugly_list.append(next_num) # 多了一个丑数 pointer += 1 return ugly_list[-1]
# -*- coding:utf-8 -*- class Solution: def GetUglyNumber_Solution(self, index): if index==0: return 0 res=[0]*index res[0]=1 t2=t3=t5=0 if index>1: for i in range(1,index): res[i]=min(res[t2]*2,res[t3]*3,res[t5]*5) if res[t2]*2==res[i]: t2+=1 if res[t3]*3==res[i]: t3+=1 if res[t5]*5==res[i]: t5+=1 return res[-1]
# -*- coding:utf-8 -*- class Solution: def GetUglyNumber_Solution(self, index): # write code here if index==0: return 0 if index==1: return 1 res=[0,1] i2,i3,i5=1,1,1 while index>1: x,y,z=res[i2]*2,res[i3]*3,res[i5]*5 if min(x,y,z)==x: tar=x i2+=1 elif min(x,y,z)==y: tar=y i3+=1 else: tar=z i5+=1 if tar!=res[-1]: res.append(tar) index-=1 return res[-1]
# -*- coding:utf-8 -*-
class Solution:
def GetUglyNumber_Solution(self, index):
# write ,code here
if index <= 0:
return 0
ans =[1]
i2= i3= i5 =0
i=0
while i<index:
# 每可执行一次while,ans的长度加一;执行到最后,当i=index时不执行
i+=1
ans.append(min(ans[i2]*2, ans[i3]*3, ans[i5]*5))
if ans[i]==ans[i2]*2:
i2+=1
if ans[i]==ans[i3]*3:
i3+=1
if ans[i]==ans[i5]*5:
i5+=1
return ans[i-1] # =ans[index-1]
""" 我是Python届的耻辱,竟然写了这么多行 Run time: 68ms Date: 2019-07-11 傍晚 模拟前面大神设置队列标准的解法,就是实现的太复杂啦,我好笨呀 """ # -*- coding:utf-8 -*- class Solution: def GetUglyNumber_Solution(self, index): # write code here if index == 1: return 1 if index == 0: return 0 ugly = 1 list1 = [2] list2 = [3] list3 = [5] for i in range(2,index+1): ugly = min(sorted(list1)[0], sorted(list2)[0], sorted(list3)[0]) ugly1 = ugly * 2 ugly2 = ugly * 3 ugly3 = ugly * 5 if ugly == list1[0]: list1.pop(0) if ugly1 not in list1: list1.append(ugly1) if ugly2 not in list2: list2.append(ugly2) if ugly3 not in list3: list3.append(ugly3) if ugly == list2[0]: list2.pop(0) if ugly1 not in list1: list1.append(ugly1) if ugly2 not in list2: list2.append(ugly2) if ugly3 not in list3: list3.append(ugly3) if ugly == list3[0]: list3.pop(0) if ugly1 not in list1: list1.append(ugly1) if ugly2 not in list2: list2.append(ugly2) if ugly3 not in list3: list3.append(ugly3) return ugly
(1)设置数组 UglyNum=[] 用来保存丑数。并将 1 添加进数组 UglyNum=[1]。基数设置为 2,3,5 。以基数为质因子的丑数的下标为 id2,idx3,idx5 ,起始均为 0 。 (2)计算: 2×UglyNum[idx2]=2×1,3×UglyNum[idx3]=3×1,5×UglyNum[idx5]=5×1 ,将最小的数存入数组 UglyNum=[1,2] ,以 2 为基数的丑数下标增加 1 : idx2=0+1=1 ,其余不变。 (3)计算: 2×UglyNum[idx2]=2×1,3×UglyNum[idx3]=3×1,5×UglyNum[idx5]=5×1 ,将最小的数存入数组 UglyNum=[1,2,3] ,以 3 为基数的丑数下标增加 1 : idx3=0+1=1 ,其余不变。 (4)计算: 2×UglyNum[idx2]=2×2,3×UglyNum[idx3]=3×2,5×UglyNum[idx5]=5×1 , 将最小的数存入数组 UglyNum=[1,2,3,4] ,以 2 为基数的丑数下标增加 1 : idx2=1+1=2 ,其余不变。 (5)计算: 2×UglyNum[idx2]=2×3,3×UglyNum[idx3]=3×2,5×UglyNum[idx5]=5×1 , 将最小的数存入数组 UglyNum=[1,2,3,4,5] ,以 5 为基数的丑数下标增加 1 : idx5=0+1=1 ,其余不变。 (6)以此类推,计算 n−1 次,并将值存入数组中。返回数组最后一个值即为所求。
def GetUglyNumber_Solution(self, index):
if index <= 1:
return index
res = [1]
t2 = t3 = t5 = 0
for i in range(1, index):
# 每次新生成的丑数是由三个数字的最小值构成的
temp = min(res[t2] * 2, res[t3] * 3, res[t5] * 5)
res.append(temp)
# 如果其中一个序列这次被选中,下一次从这个队列生成出用来比较的丑数就在这一次队列向后移动一位
if temp == res[t2] * 2:
t2 += 1
if temp == res[t3] * 3:
t3 += 1
if temp == res[t5] * 5:
t5 += 1
return res[-1]