【刷题笔记】441. 排列硬币

96 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第18天,点击查看活动详情

一、题目描述:

441. 排列硬币 - 力扣(LeetCode)

你总共有 n 枚硬币,并计划将它们按阶梯状排列。对于一个由 k 行组成的阶梯,其第 i 行必须正好有 i 枚硬币。阶梯的最后一行 可能 是不完整的。

给你一个数字 n ,计算并返回可形成 完整阶梯行 的总行数。

 

示例 1:

image.png

输入:n = 5
输出:2
解释:因为第三行不完整,所以返回 2 。

示例 2:

image.png

输入:n = 8
输出:3
解释:因为第四行不完整,所以返回 3 。

提示:

  • 1 <= n <= 2^31 - 1

二、思路分析:

x^2 + x = 2n; x = (2n - x) / x
这个方法得注意三点:
1、迭代的x不能为0,否则会返回nan,因为x会作为除数
2、牛顿迭代的结果返回的是一个近似值,该近似值在迭代的过程中不断接近真实值,但机会不可能完全等于真实值,所以它的迭代次数与你设置的精度有关,你如果直接用double类型的进度(小数点后17位),那样消耗的时间会非常长,所以最好自定义精度
3、如果第x排恰好需要n个硬币数或者十分接近,那么迭代的近似值就很有可能在一个整数的左右两次振荡,然而因为最后的答案是一个整形变量,浮点数转整形直接舍去小数部分,就可能导致最后结果错误

三、AC 代码:

class Solution {
public:
double sqrt(double x, double n) {
	double ret = (x + (2 * n - x) / x) / 2;
	if (ret > x ? (ret - x < 0.01) : (x - ret < 0.01)) {
		return ret;
	}
	else {
		return sqrt(ret, n);
	}
}


int arrangeCoins(int n) {
	if (!n) {
		return 0;
	}
		double ret = sqrt(n, n);
	long long ans = sqrt(n, n);
	long long x = ans + 1;
	if ((x + 1) * x / 2 == n) {
		return ans + 1;
	}
	else {
		return ans;
	}
}
};

范文参考:

【菜🐔题解】-「二分」-「数学公式」 - 排列硬币 - 力扣(LeetCode)