【LeetCode刷题笔记】数学

50. Pow(x, n)

解题思路:
  • 1. 绝对值 + 快速幂 + 迭代 ,由于题目 n 可能是 系统最小值 ,因此使用 n 绝对值
  • 如果 n 系统最小值 ,先让 系统最小值 +1 (最后再乘以一个 x ),这是因为 对系统最小值求绝对值还是它自身 ,但是 +1 可以在正常范围内。
  • n 的绝对值为 N 结果 res 初始为 1 只要 N 不为 0 ,就一直循环处理,每次将 x 倍乘自己,并将 N 右移 1 位, 只有 N 最低位是 1 时才把 x 累乘到结果 res 中。
  • 循环结束后,判断一下原来的 n 如果是 系统最小 ,就将 res 再乘以 1 x ,以弥补因为之前 +1 少的一个 x
  • 特判: n== 0 返回 1 (任意数的 0 次方都是 1 ), n==1 x==0 x==1 都返回 x x 1 次方还是 x 0 1 这两个数的 n 次方还是自身)。
  • 注意:最后返回的时候,需要判断如果 n 负数 ,则需要返回结果的 倒数 ,即 1 / res

解题思路:
  • 2. 快速幂 + 迭代 ,可以首先使用 long 型变量 N 来接住 n ,这样就不用担心 n 可能是 整型的最小值 了,
  • 然后对 N 取绝对值,依然是每次循环中将 x 倍乘,将 N 右移 1 位,只有 N 最低位是 1 时才把 x 乘到结果 res 中。
  • 循环结束后也不需要另外多乘了,只需要判断 n 是不是负数,是的话返回结果的倒数即可。

解题思路:
  • 3. 快速幂 + 折半递归 ,还是先使用 long 接收 n ,记为 N ,然后判断 N> 0 就调用递归  dfs(x, N) N< 0 就返回  1 / dfs(x, -N)
  • dfs 函数中接收 long 型的 N ,每次将 N 折半进行递归调用 dfs(x, N/2) ,返回结果记为 y , 然后判断如果 N 偶数 就返回 y*y ,如果 N 奇数 就返回 y*y*x
  • 递归终止:N== 0 时返回 1 N==1 时返回 x

题思路:
  • 4. 快速幂 + 折半递归 ,可以直接对 n 进行折半递归调用,返回结果记为 y ,  如果 n 是偶数,返回 y*y , 如果 n 是奇数且 n>0 , 返回 y*y*x ,如果 n 是奇数且 n<0 , 返回 y*y*(1/x)
  • 递归终止: n==0 时返回 1 n == 1时返回 x ,   n == -1时返回 1/x

 注意:当n小于0时,res需要变分母,如2的-2次方 = 1 / 2的2次方。

69. x 的平方根

解题思路:
  • 1. 二分查找 x 的平方根肯定是 [0, x] 范围内的某个数,它乘以自身得到 x , 因为大于 x 的数乘以自身结果肯定超过 x
  • 因此直接在 [0, x] 上进行 二分查找 即可,让 L R 分别指向 0 x , 每次计算出中值 mid ,
  • 然后判断如果 mid*mid ≤ x ,  记录此时的 mid 作为候选答案,然后收缩 L 到右半边 [mid + 1, R] 上搜索,否则如果 mid*mid > x ,就收缩 R 到左半边 [L, mid - 1] 上搜索。
  • 注意:在计算 mid*mid 时可能出现 整型越界 ,因此可以将所有变量使用 long 型来接受。最后返回结果时再转成 int 型。 也可以不用 long ,只需要将 mid * mid ≤  x 的判断改成 mid  x / mid ,并增加特判 x ==  或  x == 时直接返回 x ( 0 1 平方根是自身,x为这两个值时计算出的mid是0,除数不能为0 )

解题思路:
  • 2. 牛顿迭代法 ,先使用 long 型变量 a 接收 x ,然后循环判断只要 a*a > x ,就不断的将 a 更新为 (a + x / a)/ 2 , 最后返回 a 即可。(不要问我为什么这样做,问牛顿)

注意: 本题是输出整数部分,但是如果有些大厂要求结果要输出带小数的,可以使用 double 来接收 x , 最后看要求需要保留几位小数将 a 转换一下即可。
java浮点型输出2位小数:
  • 1) 可以使用 String.format("%.2f", x)
  • 2) 可以使用 new DecimalFormat(".00").format(x)
  • 3) 可以先 乘以 100 整型 除以 100.0f

263. 丑数

解题思路:
  • 1. 数学模拟 , 根据丑数的定义,首先排除 0 负数
  • n > 0 时,若  n 是丑数,则  n 可以写成 n = 2^a * 3^b * 5^c 的形式, 而当 a,b,c 都是 0 时, n=1
  • 因此可以对 n 反复除以 2,3,5 直到  n 不再包含质因数 2,3,5  为止,若最终剩下的数等于 1 ,则说明  n 不包含其他质因数,是丑数;否则不是丑数。
  • 具体地,遍历 [2,3,5] 中的 每个质因数记为 factor ,  循环判断如果  能被 factor 整除 ,就不停的让 n = n / factor  继续循环判断,直到  不能被当前的质因数整除为止。
  • 最后所有质因数都处理完了,返回  是否等于  即可。

解题思路:
  • 2. DFS , 3叉树前序遍历,从  开始,每次递归函数中访问当前根节点的三个子节点 [2,3,5] ,尝试用  除以每一个子节点,如果能除尽(没有余数),则将 [n / 当前值] 作为下一层的根节点进行DFS调用。
  • 递归终止:当 n==1 ,即遇到叶子节点时,返回 true , 说明这一条DFS支路上全部可以被 [2,3,5] 除尽
  • 递归调用中 有一个子节点返回 true ,父节点就返回 true 。 否则 最终就返回 false
  • 特判:主函数判断 n<=0 时直接返回 false ,不用进行DFS,因为丑数是正整数。

264. 丑数 II

解题思路:
  • 1. 小根堆 ,要得到从小到大的第 n 个丑数,也就是求 第  ,可以使用 小根堆 实现。
  • 初始时堆为空。首先将最小的丑数 1 加入堆。每次弹出 堆顶 元素 x 就是堆中 最小的丑数 ,由于 2x, 3x, 5x 也是丑数,因此将  2x, 3x, 5x 加入堆。
  • 上述做法会导致堆中出现 重复元素 的情况。为了避免重复元素,可以使用哈希 Set 去重,避免相同元素多次加入堆。
  • 在排除重复元素的情况下,第 n 次从最小堆中取出的元素即为第 n 个丑数。
  • 注意:每次取出堆顶再分别乘以  2、3、5  的时候,可能出现 整型溢出 ,为避免溢出问题, PriorityQueue HashSet 中可都使用 long 型存储。

整个过程实际上是一个 BFS 的过程,每取出一个节点就将该节点所属的下一层的节点放入优先级队列中: 

小根堆内部变化情况:

解题思路:
  • 2. 动态规划 ,有点类似合并三个有序数组,但是在同一个 dp 数组上进行比较的,而不是显示的三个数组,
  • 首先 dp[1] 初始为最小的丑数 1 ,然后设 3 个指针 i j k 分别指向下标 1 位置,接下来遍历 [2, n] 开始求 dp[2] dp[n] 的值,
  • 每次从 dp[i] * 2, dp[j] * 3, dp[k] * 5 三组数中选一个最小的丑数保存在 dp 中,并且 较小的那一组的指针下标向后移动一位 ,如果有 多组 都是最小值,则同时 向后移动多个指针
  • 最后返回 dp[n] 的值。

下面看一下这个算法的过程:

注意这时,第五轮之后,i 和 j 的下标会同时向后移动:

  • 20
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

川峰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值