首页 > 代码库 > LeetCode 441. Arranging Coins

LeetCode 441. Arranging Coins

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左右,差别不是很大,不过最后一种方法很是简洁。其他几种方法有助于大家对这个题目的理解。

LeetCode 441. Arranging Coins