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

  • 相关阅读:
    leetcode211
    leetcode209
    leetcode201
    leetcode1396
    leetcode1395
    leetcode1394
    leetcode1386
    leetcode1387
    leetcode1382
    leetcode1376
  • 原文地址:https://www.cnblogs.com/liujinhong/p/6024843.html
Copyright © 2011-2022 走看看