前言

大家好,今天是LeetCode每日一题的第十天,,给大家分享的是排列硬币,难度系数两颗星!废话不多说,先上题目!

1.1 题目要求

题目类型:排列硬币

题目内容

  • 总共有n枚硬币,将它们摆成一个阶梯形状,第k行就必须正好有k枚硬币。

  • 给定一个数字n,找出可形成完整阶梯的总行数。

注意事项:n是一个非负整数,并且在32位有符号整型的范围内。

1.2 解题方法

1.2.1 使用迭代法处理

1.解题思路

假设已有n枚硬币,按照题目要求把它们摆成一个阶梯形状,同时要求第k行就必须正好有k枚硬币,那么应该怎样排列呢?

假设硬币总数为10,组成阶梯状情况如下:

行数 硬币排列 剩余数量 大小比较 是否结束
1 0 9 (10-1) 9>2
2 0 0 7 (10-1-2) 7>3
3 0 0 0 4 (10-1-2-3) 4=4
4 0 0 0 0 3 (10-1-2-3-4) 0<5

注意:

  1. 硬币排列中的0表示硬币;
  2. 大小比较是指判断硬币的剩余数量与下一行的硬币个数的大小关系;
  3. 是否结束是指剩余数量是否小于等于下一行个数, 若剩余数小于下一行个数, 则排列结束,并返回当前行数
2.代码实现
  • 测试代码
package com.kuang.leetcode9;/*** @ClassName ArrangeCoin* @Description 排列硬币* @Author 狂奔の蜗牛rz* @Date 2021/8/30*/
public class ArrangeCoin {//主方法测试public static void main(String[] args) {//测试存在10个硬币时,形成完整阶梯形状返回的总行数System.out.println(arrangeCoins(10));}/*** 使用迭代法解决硬币排列问题* @param n 硬币总数(在32位有符号整型范围内的非负整数)* @return 返回值为(形成完整阶梯形状)总行数*/public static int arrangeCoins(int n) {//编写for循环体/*** 定义变量i, 表示行数* 指针i的初值为多少?* 要从第一行开始, 所以其初值为1* i的取值范围为多少?* 硬币数量i不能超过总数n, 即 i <= n*/for (int i = 1; i <= n; i++) {/*** 由于题干中要求第i行的元素也为i个,* 因此硬币剩余数量为总数n减去当前行的硬币个数i*/n = n - i;//判断n(剩余硬币数量)是否小于等于i(当前行的硬币个数)if(n <= i) {//若n(剩余数)小于i(当前行个数), 将当前行的个数i进行返回return i;}}//若当前硬币数不能组成阶梯状, 则返回的排列行数为0return 0;}
}
  • 测试结果

结果:测试结果与预期相同!

1.2.2 使用二分法查找处理

1.解题思路
  • 假设最多可以排列n行,x是第n行的硬币个数,那么每行排列的硬币个数分别为 1 2 3 4 … x;

  • 同时n为每行硬币相加之和 (即满足n=1+2+3+4+…+x),也就是说从1到n行,会存在一个x值,使得等式1+2+3+ … +x=n成立;

因此我们可以通过使用二分法从1到n行定位到那个x值

2.代码实现
  • 测试代码
package com.kuang.leetcode9;/*** @ClassName ArrangeCoin* @Description 排列硬币* @Author 狂奔の蜗牛rz* @Date 2021/8/30*/
public class ArrangeCoin {//主方法测试public static void main(String[] args) {//测试存在10个硬币时,形成完整阶梯形状返回的总行数System.out.println("使用二分法排列硬币:"+arrangeCoins2(10));}/*** 使用二分查找法处理硬币排列* @param n 硬币总数(在32位有符号整型范围内的非负整数)* @return 返回值为(形成完整阶梯形状)总行数*/public static int arrangeCoins2(int n) {//定义low和high变量, 分别表示左右指针(其初值分别为左右边界值)int low = 0, high = n;//while循环的执行条件(low左指针要小于等于high右指针)while (low <= high) {/*** mid为使用二分法查找的中值*  ----|-----|-----|---->*     low   mid   high* |<-------->| mid ?*      |<-------->|*        high - low*      |<--->|*      (high-low)/2* |<-->|<--->|*  low + (high-low)/2 = mid*/int mid = (high - low)/2 + low;/*** sum和为1到x之和, 即sum=1+2+3+4+..+x* 化简后为 1/2 * (x+1) * x = ((x+1) * x)/2*/int sum =  ((mid + 1) * mid) /2;//判断sum(硬币之和)是否等于n(硬币总数)if (sum == n) {/*** 若sum(硬币之和)值等于n(硬币总数), 说明已经排列完毕* 则直接返回mid值, 此时mid值即为完成梯形排列的最后行数*/return mid;/*** 若sum(硬币之和)值大于n(硬币总数), 说明取值范围太大,* 因此将右指针high向左移动一位(即向上移动一行)*/} else if (sum > n) {//右指针high左移一位high = mid - 1;/*** 若sum(硬币之和)值小于n(硬币总数), 说明取值范围太小,* 因此将左指针low向右移动一位(即向下移动一行)*/} else {//左指针low右移一位low = mid + 1;}}//最后将high右指针值进行返回(此时high值为满足排列的总行数)return high;}}
  • 测试结果

结果:测试结果与预期相同!

1.2.3 使用牛顿迭代法处理

1.解题思路

牛顿迭代公式:(x + n / x) / 2

需要满足的条件:(x + 1)x / 2 = n

我们将它进一步进行转化:

(x + 1) x = 2n => x * x + x = 2n => x * x = 2n - x

即x的平方等于2n减去x,x的平方相当于牛顿迭代公式中的n

我们只需将x的平方代入到上面的牛顿迭代公式中去,直到求出预期结果为止!

2.代码实现
  • 测试代码
package com.kuang.leetcode9;/*** @ClassName ArrangeCoin* @Description 排列硬币* @Author 狂奔の蜗牛rz* @Date 2021/8/30*/
public class ArrangeCoin {//主方法测试public static void main(String[] args) {//测试存在10个硬币时,形成完整阶梯形状返回的总行数System.out.println("使用牛顿迭代法排列硬币:"+arrangeCoins3(10));}/*** 牛顿迭代求平方根* @param x 排列总行数(未知值)* @param n 硬币总个数(已知值)* @return*/private static double sqrt(double x, int n) {/*** 定义res返回结果值* 牛顿迭代公式: (x + n/x)/2* 满足条件代入: n = x * x = 2n - x* 即res值为(x + (2n -x)/x)/2*/double res = (x + (2 * n - x)/x)/2;//判断res(返回结果)值是否等于x(排列总行数)if (res == x) {//若满足条件, 则将x值返回(此时x值为满足条件的排列总行数)return x;} else {//若不满足条件, 则进行递归调用(将res结果值作为下一轮的x值)return sqrt(res, n);}}}
  • 测试结果

结果:测试结果与预期相同!


好了,今天LeetCode每日一题—排列硬币到这里就结束了,欢迎大家学习和讨论,点赞和收藏!


参考视频链接:https://www.bilibili.com/video/BV1Ey4y1x7J3 (国内算法宝典-LeetCode算法50讲)

LeetCode每日一题之排列硬币相关推荐

  1. LeetCode 每日一题 42. 接雨水 详细多种题解 C++描述

    LeetCode 每日一题 42. 接雨水 大家好,我叫亓官劼(qí guān jié ),在CSDN中记录学习的点滴历程,时光荏苒,未来可期,一起加油吧~ 难度 困难 2020.04.04每日一题 ...

  2. leetcode每日刷题计划-简单篇day8

    leetcode每日刷题计划-简单篇day8 今天是纠结要不要新买手机的一天QAQ想了想还是算了吧,等自己赚钱买,加油 Num 70 爬楼梯 Climbing Stairs class Solutio ...

  3. Leetcode每日一题:171.excel-sheet-column-number(Excel表列序号)

    思路:就是168题的反命题,进制的方式完美解决: Leetcode每日一题:168.excel-sheet-column-title(Excel表名称) class Solution {public: ...

  4. 【LeetCode每日一题】1723. 完成所有工作的最短时间

    [LeetCode每日一题]1723. 完成所有工作的最短时间 [1] 1723. 完成所有工作的最短时间 [2] 473. 火柴拼正方形 [1] 1723. 完成所有工作的最短时间 题目: 给你一个 ...

  5. leetcode每日一题--雀巢原理;抽屉算法;Quorum机制;分布式应用

    leetcode每日一题 539. 最小时间差 示例 1: 输入:timePoints = ["23:59","00:00"] 输出:1 示例 2: 输入:ti ...

  6. LeetCode每日一题——1812. 判断国际象棋棋盘中一个格子的颜色

    LeetCode每日一题系列 题目:1812. 判断国际象棋棋盘中一个格子的颜色 难度:简单 文章目录 LeetCode每日一题系列 题目 示例 思路 题解 题目 给你一个坐标 coordinates ...

  7. 【LeetCode每日一题】——109.有序链表转换二叉搜索树

    文章目录 一[题目类别] 二[题目难度] 三[题目编号] 四[题目描述] 五[题目示例] 六[题目提示] 七[解题思路] 八[时间频度] 九[代码实现] 十[提交结果] 一[题目类别] 二叉树 二[题 ...

  8. leetcode每日一题·救生艇问题(Python)

    leetcode每日一题·救生艇问题(Python) 问题描述 题目入口 题目思路 首先分析问题,一个船最多坐两人,因此我们可以把这个问题看作两两组合的问题,并且如果最重的那个人和最轻的人加起来大于l ...

  9. LeetCode每日一题——904. 水果成篮

    LeetCode每日一题系列 题目:904. 水果成篮 难度:普通 文章目录 LeetCode每日一题系列 题目 示例 思路 题解 题目 你正在探访一家农场,农场从左到右种植了一排果树.这些树用一个整 ...

最新文章

  1. 查看MS SQL Server数据库每个表占用的空间大小
  2. HTTPS协议,SSL协议及完整交互过程
  3. 单独组件_苹果已停止对macOS Big Sur 11.0.1版本macOS系统组件的单独更新
  4. 将自己写的经常复用的类封装成动态库的方法
  5. JavaScript中window对象属性,时间等的总结
  6. 【机器视觉】 endtry算子
  7. 【性能优化】 之 并行执行
  8. 量化交易,量化分析推荐书单
  9. 2020年有赞云生态发展白皮书
  10. SQL联合主键 查重
  11. Nginx学习总结(10)——Nginx前后端分离将多个请求转发到多个Tomcat,负载均衡反向代理
  12. Web前端笔记(1)
  13. 如何修改MySQL已有表的字符集
  14. 新鲜出炉的头条面试算法
  15. 体验下Xcode5与ios7
  16. 【OpenCV学习笔记】【函数学习】十六(Rect参数介绍)
  17. 廊坊金彩教育:店铺运营技巧思路
  18. 大疆FPGA/芯片开发工程师(A卷)笔试题(含详解)
  19. js银行卡、手机号等校验汇总
  20. 附录H-2 技术预研报告

热门文章

  1. Stream流中collect方法
  2. 百度惊雷算法3.0即将上线(终于开始整治SEO快排行业了)
  3. 基于人体姿势估计的舞蹈检测(AI Dance based on Human Pose Estimation)
  4. python全自动模拟_数十行 Python 代码全自动刷王者荣耀金币
  5. jdom编写xml自动缩进_2020学习python技巧资料之python缩进规则
  6. 计算机科学与技术班级口号八字,霸气八字班级口号_班级口号大全霸气十足
  7. 微软官网U启动制作工具安装window10系统
  8. MT6750详细芯片资料分享 MT6750设计原理图须知
  9. 域名的年龄对SEO影响有哪些?为什么老域名有利于SEO?
  10. MCE | 正确认识阿尔茨海默病