排列硬币
总共有 n 枚硬币,将它们摆成一个阶梯形状,第 k 行就必须正好有 k 枚硬币。给定一个数字 n,找出可形成完整阶梯行的总行数。n 是一个非负整数,并且在32位有符号整型的范围内。
示例 1:
输入:n = 5
输出:2
解释:因为第三行不完整,所以返回 2 。
示例 2:
输入:n = 8
输出:3
解释:因为第四行不完整,所以返回 3 。
解法一:迭代
从第一行开始排列,排完一列、计算剩余硬币数,排第二列,直至剩余硬币数小于或等于行数
解法二:二分查找
假设能排 n 行,计算 n 行需要多少硬币数,如果大于 n,则排 n/2行,再计算硬币数和 n 的大小关系
解法三:牛顿迭代
使用牛顿迭代求平方根,(x + n/x)/2
假设能排 x 行 则 1 + 2 + 3 + …+ x = n,即 x(x+1)/2 = n 推导出 x = 2n – x
package od; /** * 排列硬币(3种解法) * 总共有 n 枚硬币,将它们摆成一个阶梯形状,第 k 行就必须正好有 k 枚硬币。 * 给定一个数字 n,找出可形成完整阶梯行的总行数。 * n 是一个非负整数,并且在32位有符号整型的范围内。 * 原文地址:https://www.codernav.com/2832.html * 更多算法详解:https://www.codernav.com */ public class OdTest27 { public static void main(String[] args) { // 解法一:迭代 System.out.println(f1(10)); // 解法二:二分.查找 System.out.println(f2(10)); // 解法三:牛顿.迭代 System.out.println(f3(10)); } public static int f1(int n) { // i代表第i行,也代表这行有i个硬币 for (int i = 1; i <= n; i++) { // n代表剩余硬币数量 n = n - i; // 剩余硬币个数小于这行需要的硬币个数 if (n <= i) { return i; } } return 0; } public static int f2(int n) { int low = 0, high = n; while (low <= high) { long mid = (high - low) / 2 + low; long cost = ((mid + 1) * mid) / 2; if (cost == n) { return (int) mid; } else if (cost > n) { high = (int) mid - 1; } else { low = (int) mid + 1; } } return high; } public static int f3(int n) { if (n == 0) { return 0; } return (int) sqrts(n, n); } public static double sqrts(double x, int n) { double res = (x + (2 * n - x) / x) / 2; if (res == x) { return x; } else { return sqrts(res, n); } } }
© 版权声明
文章版权归作者所有,未经允许请勿转载。
相关文章
暂无评论...