C#LeetCode刷题之#441-排列硬币(Arranging Coins)
问题
该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/3995 访问。
你总共有 n 枚硬币,你需要将它们摆成一个阶梯形状,第 k 行就必须正好有 k 枚硬币。
给定一个数字 n,找出可形成完整阶梯行的总行数。
n 是一个非负整数,并且在32位有符号整型的范围内。
n = 5
硬币可排列成以下几行:
¤
¤ ¤
¤ ¤因为第三行不完整,所以返回2.
n = 8
硬币可排列成以下几行:
¤
¤ ¤
¤ ¤ ¤
¤ ¤因为第四行不完整,所以返回3.
You have a total of n coins that you want to form in a staircase shape, where every k-th row must have exactly k coins.
Given n, find the total number of full staircase rows that can be formed.
n is a non-negative integer and fits within the range of a 32-bit signed integer.
n = 5
The coins can form the following rows:
¤
¤ ¤
¤ ¤Because the 3rd row is incomplete, we return 2.
n = 8
The coins can form the following rows:
¤
¤ ¤
¤ ¤ ¤
¤ ¤Because the 4th row is incomplete, we return 3.
示例
该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/3995 访问。
public class Program {
public static void Main(string[] args) {
var n = 8;
var res = ArrangeCoins(n);
Console.WriteLine(res);
n = 18;
res = ArrangeCoins2(n);
Console.WriteLine(res);
n = 28;
res = ArrangeCoins3(n);
Console.WriteLine(res);
n = 38;
res = ArrangeCoins4(n);
Console.WriteLine(res);
n = 58;
res = ArrangeCoins5(n);
Console.WriteLine(res);
n = 68;
res = ArrangeCoins6(n);
Console.WriteLine(res);
Console.ReadKey();
}
private static int ArrangeCoins(int n) {
//暴力解法,此解法LeetCode超时未AC
var res = 0;
var value = (long)0;
while(n > (value = ComputerT(++res))) { }
if(n != value) res--;
return res;
//以下解法同理,但 LeetCode 可以 AC
//if(n == 0) return 0;
//for(long i = 1; ; i++) {
// if(n >= (i + 1) * i / 2 && n < (i + 2) * (i + 1) / 2)
// return (int)i;
//}
}
private static int ComputerT(int n) {
//抽出来是为了让程序结构更清晰
return (1 + n) * n / 2;
}
private static int ArrangeCoins2(int n) {
//按1、2、3、4、5这样一直减下去
//直到n小于或等于0时为止
var index = 1;
while((n -= index++) > 0) { }
//考虑上述循环中因为是 index++
//index最终被多加了一次
//真实的索引应该是 index - 1
index--;
//小于0时,最后一排不完整,所以再减1
if(n < 0) return index - 1;
//等于0时,最后一徘正好完整
return index;
}
private static int ArrangeCoins3(int n) {
/* 推导过程
*
* 说明=>x ^ 2 表示 x 的平方
* 公式1:a ^ 2 + 2 * a * b + b ^ 2 = (a + b) ^ 2
* 公式2:公差为1的等差数列的求和公式为 S = (1 + n) * n / 2
*
* 推导=>
* 设在第 k 行硬币排完,那么
* (1 + k) * k / 2 = n
* 展开并两边同时乘以 2
* k + k ^ 2 = 2 * n
* 两边同时 + 0.25
* k ^ 2 + k + 0.25 = 2 * n + 0.25
* 合并
* (k + 0.5) ^ 2 = 2 * n + 0.25
* 两边同时开根号
* k + 0.5 = Math.Sqrt(2 * n + 0.25)
* 两边同时 - 0.5,求出 k 的值
* k = Math.Sqrt(2 * n + 0.25) - 0.5
*/
//原来的 n 为int,直接 2 * n + 0.25 会导致值溢出
//所以用 (long)n 强转
return (int)(Math.Sqrt(2 * (long)n + 0.25) - 0.5);
//以下解法同理,但换了一种求 k 的方式
//具体推导过程请看以下博文
//https://blog.csdn.net/zx2015216856/article/details/81950377
//return (int)((Math.Sqrt(8 * (long)n + 1) - 1) / 2);
}
private static int ArrangeCoins4(int n) {
//解法思路同ArrangeCoins
//都属于暴力求解,但此解法效率略高,可AC
var x = (long)n;
var temp = (long)n;
while(x * x + x > 2 * temp) {
x = (x * x + 2 * temp) / (2 * x + 1);
}
return (int)x;
}
private static int ArrangeCoins5(int n) {
//基本思路同ArrangeCoins和ArrangeCoins4
var k = (int)(Math.Sqrt(2) * Math.Sqrt(n));
return k * (k + 1) <= 2 * n ? k : k - 1;
}
private static int ArrangeCoins6(int n) {
//二分法
//二分是对暴力解法的优化
//使得循环更快的靠近目标
var left = 0L;
var right = (long)n;
while(left <= right) {
var mid = left + (right - left) / 2;
var sum = mid * (mid + 1) / 2;
if(sum > n) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return (int)(left - 1);
}
}
以上给出6种算法实现,以下是这个案例的输出结果:
该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/3995 访问。
3
5
7
8
10
11
分析:
显而易见,ArrangeCoins、ArrangeCoins2、ArrangeCoins4、ArrangeCoins5的时间复杂度均为: ,ArrangeCoins3的时间复杂度基于 Math.Sqrt() 的实现,ArrangeCoins6的时间复杂度为:
。
C#LeetCode刷题之#441-排列硬币(Arranging Coins)的更多相关文章
- Leetcode之二分法专题-441. 排列硬币(Arranging Coins)
Leetcode之二分法专题-441. 排列硬币(Arranging Coins) 你总共有 n 枚硬币,你需要将它们摆成一个阶梯形状,第 k 行就必须正好有 k 枚硬币. 给定一个数字 n,找出可形 ...
- [Swift]LeetCode441. 排列硬币 | Arranging Coins
You have a total of n coins that you want to form in a staircase shape, where every k-th row must ha ...
- C#LeetCode刷题-二分查找
二分查找篇 # 题名 刷题 通过率 难度 4 两个排序数组的中位数 C#LeetCode刷题之#4-两个排序数组的中位数(Median of Two Sorted Arrays)-该题未达最优解 30 ...
- C#LeetCode刷题-数学
数学篇 # 题名 刷题 通过率 难度 2 两数相加 29.0% 中等 7 反转整数 C#LeetCode刷题之#7-反转整数(Reverse Integer) 28.6% 简单 8 字符串转整数 ...
- Java实现 LeetCode 441 排列硬币
441. 排列硬币 你总共有 n 枚硬币,你需要将它们摆成一个阶梯形状,第 k 行就必须正好有 k 枚硬币. 给定一个数字 n,找出可形成完整阶梯行的总行数. n 是一个非负整数,并且在32位有符号整 ...
- LeetCode刷题总结-数组篇(中)
本文接着上一篇文章<LeetCode刷题总结-数组篇(上)>,继续讲第二个常考问题:矩阵问题. 矩阵也可以称为二维数组.在LeetCode相关习题中,作者总结发现主要考点有:矩阵元素的遍历 ...
- LeetCode刷题总结-数组篇(下)
本期讲O(n)类型问题,共14题.3道简单题,9道中等题,2道困难题.数组篇共归纳总结了50题,本篇是数组篇的最后一篇.其他三个篇章可参考: LeetCode刷题总结-数组篇(上),子数组问题(共17 ...
- LeetCode刷题总结-树篇(上)
引子:刷题的过程可能是枯燥的,但程序员们的日常确不乏趣味.分享一则LeetCode上名为<打家劫舍 |||>题目的评论: 如有兴趣可以从此题为起点,去LeetCode开启刷题之 ...
- C#LeetCode刷题-动态规划
动态规划篇 # 题名 刷题 通过率 难度 5 最长回文子串 22.4% 中等 10 正则表达式匹配 18.8% 困难 32 最长有效括号 23.3% 困难 44 通配符匹配 17.7% ...
随机推荐
- 记一次webpack打包的问题
记一次webpack打包的问题 在webpack打包中开启了webpack-bundle-analyzer,发现了一个chunk:tinymce  在整个项目中查找,只有一个未被使用的组件中有如下代 ...
- 学习mysql,你必须要了解的 “ 索引 ” 基本知识
1.select * 对效率的影响在我们平时的代码编写或面试题中,很多人都会疑惑:select * 到底合理吗? 如果说不合理,为什么?如果说合理,原因又是什么? 1).阿里规范 在阿里java规范中 ...
- Makefile中自动生成头文件依赖
为什么需要自动生成头文件依赖? 编译单个源文件时,需要获取文件中包含的头文件的信息,但是一般的Makefile不会在规则中明确写明文件依赖的头文件,所以单独修改头文件后,不会导致包含头文件的源文件重新 ...
- 像计算机科学家一样思考Python(第2版)|百度网盘免费下载|Python新手入门资料
像计算机科学家一样思考Python(第2版)|百度网盘免费下载 提取码:01ou 内容简介 · · · · · · 本书以培养读者以计算机科学家一样的思维方式来理解Python语言编程.贯穿全书的主 ...
- iPhone截长图的方法
iPhone手机暂没有长图截取功能,所以我们只能通过别的方式进行长图截取. (2020年4月10日更新) ios13目前可以截长图了,不过只能在Safari中进行长图截取,而且存储形式为pdf格式,下 ...
- Servlet学习之Maven导入Servlet-api包与Tomcat冲突报500问题
Maven导入Servlet-api包导致无法运行报500的问题 以下解决方式适用于跟我类似的配置环境,构建servlet程序后,启动Tomcat页面报"类com.tioxy.servlet ...
- 最基本的Tkinter界面操作
1.创建应用程序主窗口对象 root = Tk() 2.在主窗口中,添加各种可视化组件 btn1 = Button(root) btn1["text"] = "点我&qu ...
- ElasticJob和SpringBoot
本文以在SpringBoot下集成ElasticJob的方式对其进行浅析,仅仅是简单使用,不涉及源码级别研究. 事先必备: 注册中心——zookeeper 简略结构: 代码目录结构: ├─.idea ...
- 省选模拟赛day4
怎么说?发现自己越来越菜了 到了不写题解写不出来题目的地步了.. 这次题目我都有认真思考 尽管思考的时候状态不太好 但是 我想 再多给我时间也思考不出来什么吧 所以写一份题解. T1 n个点的有根树 ...
- InvalidProgramException: Specifying keys via field positions is only valid for tuple data types
Run Flink实例时,出现如下错误: 原因:Java程序引用了Scala的Tuple2类 遇到的坑,记录下来!