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% ...
随机推荐
- 面试锦囊 | HTTP 面试门路
前言 本文已经收录到我的 Github 个人博客,欢迎大佬们光临寒舍: 我的 Github 博客 学习清单: 零.前置知识 幂等的概念是指同一个请求方法执行多次和仅执行一次的效果完全相同 一.PUT ...
- Selenium自动化:有代码测试与无代码测试。这些你都懂了吗?
大多数测试人员认为 Selenium是满足其测试自动化需求的自动化框架.作为全球测试人员使用的开放源框架, Selenium 无疑是测试人员适应日趋敏捷的公司的一种好方法.实际上, Selenium仍 ...
- java并发编程[持续更新]
目录 java并发编程 1.常用类介绍 Semaphore 2.名词解释 2.1 线程安全 2.2 可重入锁和不可重入锁 java并发编程 1.常用类介绍 Semaphore Semaphore 类是 ...
- NIO入门之缓冲区Buffer
缓存区 Buffer 是数据容器 ByteBuffer 可以存储除了 boolean 以外的其他 7 种Java基本数据类型,如 getInt.putInt Buffer 是抽象类,它有除了 Bool ...
- Nginx(一)Linux上的Nginx安装步骤
一.Windows下安装 解压:nginx-windows 双击: nginx.exe 能看到nginx欢迎界面说明,nginx安装成功 演示下 nginx做静态服务器 二.Linux下安装 (1). ...
- Object#wait()与Object#wait(long)的区别
例子 例1 最基础的等待-通知 下面一个例子,一个线程"waiting"在同步代码块调用了Object#wait()方法,另一个线程"timedWaiting" ...
- makefile for Linux纯小白版
某大佬曾说过: 不会makefile,不要说你会linux,因为makefile是合格程序员的必经之路 首先你要有个vi或者emacs 之类的编辑器 编写几个程序 test1.c #include&l ...
- java图片压缩工具类(指定压缩大小)
1:先导入依赖 <!--thumbnailator图片处理--> <dependency> <groupId>net.coobird</groupId> ...
- 7.6 NOI模拟赛 灯 根号分治
比较容易想的题目~ 容易发现 点亮一种颜色的贡献=新增灯的数量-已经存在的边的条数. 用线段树维护并不容易.暴力的话复杂度是\(Q\cdot n\)的. 考虑根号分治 只单纯考虑度数<B的点的话 ...
- 4.18 省选模拟赛 无聊的计算器 CRT EXBSGS EXLucas
算是一道很毒瘤的题目 考试的时候码+调了3h才搞定. op==1 显然是快速幂. op==2 有些点可以使用BSGS 不过后面的点是EXBSGS. 这个以前学过了 考试的时候还是懵逼.(当时还是看着花 ...