I. 263. 丑数(是否为丑数)

一、题目描述

编写一个程序判断给定的数是否为丑数

丑数就是只包含质因数 2, 3, 5 的正整数。

示例 1:

输入: 6
输出: true
解释: 6 = 2 × 3

示例 2:

输入: 8
输出: true
解释: 8 = 2 × 2 × 2

示例 3:

输入: 14
输出: false
解释: 14 不是丑数,因为它包含了另外一个质因数 7。

说明:

  • 1 是丑数。
  • 输入不会超过 32 位有符号整数的范围: [ − 2 31 , 2 31 − 1 ] [−2^{31}, 2^{31} − 1] [−231,231−1]。

二、解题思路 & 代码

2.1 循环迭代

class Solution:def isUgly(self, num: int) -> bool:if(num==0):return Falseif(num==1):return Truewhile(num%2==0):num //=2while(num%3==0):num //=3while(num%5==0):num //=5return num==1

2.2 递归

class Solution:def isUgly(self, num: int) -> bool:if(num==0): return Falseif(num==1):return Trueif(num%2==0):return self.isUgly(num // 2)if(num%3==0):return self.isUgly(num // 3)if(num%5==0):return self.isUgly(num // 5)return False

======================================================

II. 264. 丑数(找第 n n n 个丑数)

一、题目描述

写一个程序,找出第 n 个丑数

丑数就是质因数只包含 2, 3, 5 的正整数。

示例:

输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。

说明:

  • 1 是丑数。
  • n 不超过1690。

二、解题思路 & 代码

2.1 动态规划

d p [ i ] dp[i] dp[i] 表示第 i 个丑数
前面的每一个数(状态)都可以乘上 2, 3, 5 来形成一个新的状态

创建 3 个指针 p2、p3、p5,分别表示这 3 个质数因子此时应该乘上第几个状态。

p2、p3、p5 的含义

实际上 p i pi pi 的含义是有资格同 i i i 相乘的最小丑数的位置。

这里资格指的是:如果一个丑数 d p [ p i ] dp[pi] dp[pi] 通过乘以 i i i 可以得到下一个丑数,那么这个丑数 d p [ p i ] dp[pi] dp[pi] 就永远失去了同 i i i 相乘的资格(没有必要再乘了),我们把 p i + + pi++ pi++ 让 d p [ p i ] dp[pi] dp[pi] 指向下一个丑数即可。

举例说明:

  • 一开始,丑数只有{1},1可以同 2 、3 、5 相乘,取最小的 1 × 2 = 2 添加到丑数序列中。
  • 现在丑数中有 {1,2} ,在上一步中,1 已经同 2 相乘过了,所以今后没必要再比较 1 × 2 了,我们说 1 失去了同 2 相乘的资格。
  • 现在 1 有与 3、5 相乘的资格,2 有与 2、3、5 相乘的资格,但是 2 × 3 和 2 × 5 是没必要比较的,因为有比它更小的 1 可以同 3、5 相乘,所以我们只需要比较 1 × 3 、1 × 5 、 2 × 2 。

依此类推,每次我们都分别比较有资格同 2、3、5 相乘的最小丑数,选择最小的那个作为下一个丑数,假设选择到的这个丑数是同 i( i = 2、3、5)相乘得到的,所以它失去了同 i 相乘的资格,把对应的 pi++ ,让 pi 指向下一个丑数即可。

class Solution:def nthUglyNumber(self, n: int) -> int:if( n < 1):return 0p2 = 0p3 = 0p5 = 0dp = [0] * ndp[0] = 1for i in range(1, n):# 比较此时可能的状态,取最小的那个dp[i] = min(dp[p2] * 2, min(dp[p3] * 3, dp[p5] * 5))# 更新指向# 注意这里不能只更新一个指针# 比如 6,可以由 2 * 2 * 2 形成,也可以由 2 * 3 组成if( dp[i] == dp[p2] * 2): p2 += 1if( dp[i] == dp[p3] * 3): p3 += 1if( dp[i] == dp[p5] * 5): p5 += 1return dp[n - 1]

复杂度分析

  • 时间复杂度: O(n)。生成一个丑数只需常量时间,所以生成n个丑数需要 O(n)。
  • 空间复杂度:O(n)。dp数组的长度为n。

参考:

  1. 字节跳动面到这道题,有的读者一脸懵逼,有的读者笑嘻嘻

2.2 优先队列(小顶堆)

利用优先队列有自动排序的功能

生成丑数的规律:如果已知丑数 ugly ,那么 ugly * 2,ugly * 3 和 ugly * 5 也都是丑数。

既然求第n小的丑数,可以采用最小堆来解决。每次弹出堆中最小的丑数,然后检查它分别乘以2、3和 5后的数是否生成过,如果是第一次生成,那么就放入堆中。第n个弹出的数即为第n小的丑数。

具体:每次取出队头元素,存入队头元素 *2、队头元素 *3、队头元素 *5
但注意,像12这个元素,可由 43得到,也可由62得到,所以要注意去重

########################## 比较慢 ################################
# class Solution:
#     def nthUglyNumber(self, n: int) -> int:
#         c = set()
#         m = 1
#         stack = [1]
#         d = []
#         while len(d) < n:
#             m = min(stack)
#             stack.remove(m)
#             d.append(m)
#             if m * 2 not in c:
#                 stack.append(m * 2)
#                 c.add(m * 2)
#             if m * 3 not in c:
#                 stack.append(m * 3)
#                 c.add(m * 3)
#             if m * 5 not in c:
#                 stack.append(m * 5)
#                 c.add(m * 5)
#         return d[n - 1]########################## 比较快 ################################
import heapqclass Solution:def nthUglyNumber(self, n: int) -> int:heap = []heapq.heappush(heap, 1)seen = set()seen.add(1)factors = [2, 3, 5]curr_ugly = 1for _ in range(n):curr_ugly = heapq.heappop(heap)for f in factors:new_ugly = curr_ugly * fif new_ugly not in seen:seen.add(new_ugly)heapq.heappush(heap, new_ugly)return curr_ugly

复杂度分析

  • 时间复杂度: O(nlog(n))。弹出每个最小值时,时间复杂度都为堆的高度,因此时间复杂度为O(nlog(n)) 。
  • 空间复杂度: O(n)。遍历n个丑数,并将每个丑数乘以 2、3 和 5 的结果存入堆中。堆和哈希表的元素个数都不会超过 n * 3。

参考:

  1. LeetCode题解

【LeetCode】263.丑数 264. 丑数 II相关推荐

  1. LeetCode 263. 丑数 264. 丑数 II(DP)

    文章目录 1. LeetCode 263. 丑数 解题 2. LeetCode 264. 丑数 II DP解题 1. LeetCode 263. 丑数 编写一个程序判断给定的数是否为丑数. 丑数就是只 ...

  2. leetcode 263, 264, 1201, 313. Ugly Number I, II, III, Super Ugly Number(leetcode 丑数问题合集)

    263. Ugly Number https://leetcode.com/problems/ugly-number/ 本题题解由下面的 264. Ugly Number II 改造而来,所以效率会比 ...

  3. leetcode - 264. 丑数 II

    264. 丑数 II -------------------------------------------- 编写一个程序,找出第 n 个丑数. 丑数就是只包含质因数 2, 3, 5 的正整数. 示 ...

  4. LeetCode 264. 丑数 II

    264. 丑数 II Ideas 竟然没想到用小根堆,白学了,再把小根堆抄一遍. Code Python class Solution:def nthUglyNumber(self, n: int) ...

  5. 86. Leetcode 264. 丑数 II (动态规划-基础题)

    给你一个整数 n ,请你找出并返回第 n 个 丑数 .丑数 就是只包含质因数 2.3 和/或 5 的正整数.示例 1:输入:n = 10 输出:12 解释:[1, 2, 3, 4, 5, 6, 8, ...

  6. 78. Leetcode 264. 丑数 II (堆-技巧二-多路归并)

    给你一个整数 n ,请你找出并返回第 n 个 丑数 .丑数 就是只包含质因数 2.3 和/或 5 的正整数.示例 1:输入:n = 10 输出:12 解释:[1, 2, 3, 4, 5, 6, 8, ...

  7. leetcode 264. 丑数 II(堆)

    给你一个整数 n ,请你找出并返回第 n 个 丑数 . 丑数 就是只包含质因数 2.3 和/或 5 的正整数. 示例 1: 输入:n = 10 输出:12 解释:[1, 2, 3, 4, 5, 6, ...

  8. LeetCode 264.丑数 II(动态规划)

    题目描述 编写一个程序,找出第 n 个丑数. 丑数就是只包含质因数 2, 3, 5 的正整数. 示例: 输入: n = 10 输出: 12 解释: 1, 2, 3, 4, 5, 6, 8, 9, 10 ...

  9. LeetCode 264. 丑数 II--动态规划

    丑数 II 编写一个程序,找出第 n 个丑数. 丑数就是质因数只包含 2, 3, 5 的正整数. 示例: 输入: n = 10 输出: 12 解释: 1, 2, 3, 4, 5, 6, 8, 9, 1 ...

最新文章

  1. 一文详解CMake编译工具与项目构建
  2. 【性能优化】 之 几种常见的等待事件的演示示例
  3. Commons里的DButil
  4. 换股也是一种解套方法
  5. 5个Linux 服务器发行版你值得拥有
  6. 让菜鸡讲一讲网络流(isap)
  7. 算法笔记_面试题_20.数组相关_模板及示例十几道
  8. python对医学图像的基本处理_python OpenCV 实现图片的医学处理
  9. Windbg调试工具介绍
  10. Docer容器客户端在启动的镜像的时候报错Error invoking remote method ‘docker-start-container‘: Error: (HTTP code 500
  11. 微信小程序云开发——图片展示,视频播放案例
  12. 计算机进去bios方式,电脑进入BIOS的两种实用方法
  13. 2022元宇宙十大 “闪光时刻”
  14. SpringBoot启动时:Process finished with exit code 0解决办法
  15. 素雅的登录界面,简单而优雅
  16. 【架构】分布式系统及相关技术栈初了解
  17. HAL层,.sensors.h 头文件分析
  18. 王小波经典语录/名句
  19. 无言以队——需求规格说明书
  20. 微信朋友圈点赞如何设计测试用例,微信发语音消息,购物车,支付页面如何设计软件测试用例?

热门文章

  1. [springboot]springboot启动流程
  2. 学校热水系统服务认证
  3. 包装类,正则表示式,Arrays类
  4. 计算机二级vb必背,【2015年必备】全国计算机二级VB公共基础知识总汇(熟记必过,不看后悔).doc...
  5. 基于ART-PI SPI驱动W25Q128
  6. web3再牛 也没能逃出这几个老巨头的手掌心
  7. Unity制作见缝插针小游戏项目实战
  8. 15、项目:见缝插针游戏---界面
  9. steam游戏上架流程四:Steamworks SDK 的API 方法回调方式 ( Callback )
  10. 一点体会:找工作这事儿