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.
Example 1:
n = 5 The coins can form the following rows: ¤ ¤ ¤ ¤ ¤ Because the 3rd row is incomplete, we return 2.
Example 2:
n = 8 The coins can form the following rows: ¤ ¤ ¤ ¤ ¤ ¤ ¤ ¤ Because the 4th row is incomplete, we return 3.
【题目分析】
题目很简单,实际是一个等差数列。等差数列的求和公式为:k(k+1)/2
【思路】
1. 直接遍历即可,从1开始,如果剩下是数不能构成一行则返回。注意要先判断剩下的数是否满足,而不是累加以后再判断,这样可能会导致溢出。
2. 牛顿法
结合前面的题目,发现这个题目也可以用牛顿法来解决,实际求的是x*(x+1)/2 - n = 0时x的值。
利用牛顿法导出递推关系式:xi+1 = (xi*xi+2*n) / (2*xi+1)
牛顿法可以参考:http://www.cnblogs.com/liujinhong/p/6014973.html
在这自编sqrt()函数的题目中也用到了牛顿法,但是牛顿法的结果会有一些坑,大家在使用的时候要注意。有些情况下牛顿法只能收敛到某个精度,收敛值可能会在最后几个值中循环变动。所以最好自己确定收敛精度,并对最后的结果进行判断后再返回值。在这个题目中我使用牛顿法只是一种尝试,不建议大家使用。
3. 直接推导结果
直接看公式就可以了
/* 数学推导
假设完成K层,一共N个,由等差数列求和公式有:
(1+k)*k/2 = n
一步步推导:
k+k*k = 2*n
k*k + k + 0.25 = 2*n + 0.25
(k + 0.5) ^ 2 = 2*n +0.25
k + 0.5 = sqrt(2*n + 0.25)
k = sqrt(2*n + 0.25) - 0.5
这里k是个浮点数,将其取为小于k的最大整数就可以
*/
【java代码1】
1 public class Solution { 2 public int arrangeCoins(int n) { 3 if(n < 1) return 0; 4 int count = 0,i; 5 for(i=1; n-count>=i; i++){ 6 count += i; 7 } 8 return i-1; 9 } 10 }
【java代码之牛顿法】
1 public class Solution { 2 public int arrangeCoins(int n) { 3 if(n < 1) return 0; 4 double last = 0, res = 1,num = n; 5 6 while(Math.abs(last-res) > 10e-3) { 7 last = res; 8 res = (res*res + 2*num) / (2*res + 1); 9 } 10 11 int count = (int)res; 12 int rest = count%2 == 0? n-(count/2)*(count+1): n-count*((count+1)/2); 13 return rest <= count? count: count+1; 14 } 15 }
【java代码math推导方法】
1 public class Solution { 2 public int arrangeCoins(int n) { 3 return (int) (Math.sqrt(2*(long)n+0.25) - 0.5); 4 } 5 }
这些方法的运行时间大概都在50ms左右,差别不是很大,不过最后一种方法很是简洁。其他几种方法有助于大家对这个题目的理解。