Title address: https://leetcode.com/problems/arranging-coins/description/
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.
// two methods
method one:
class Solution { public int arrangeCoins(int n) { long lo = 1, hi = n; // The definition of lo and hi as long is purely for the convenience of mid assignment, and the int range is enough long mid; if (n == 0) return 0; while (hi - lo > 1) { mid = (lo + hi) >>> 1; // here mid should define long, although there will not be a problem with mid due to addition overflow, but the following expression mid*(1+mid)>>>1 By default int, multiplication overflow may occur, far beyond the range of int, and the extra high-order part of the binary has been truncated, which will lead to incorrect results. long sum = mid * (1 + mid) >>> 1; // sum must be long because the int value is 2147483647 and one step will get 1297036691877396480 if (sum > n) { hi = mid; } else { lo = mid; } } return (int)lo; } }
If you think mid=(lo+hi)>>>1 is difficult to understand, then replace it with mid=lo + ((hi - lo) >>1), because lo is in the int range, hi is in the int range, and hi- lo is also in the int range, and lo+(hi-lo)>>1 is less than hi, so it is also in the int range. About why >>>1 is better, you can read my other blog: https://blog.csdn.net/qq_34115899/article/details/79859973
But >>>1 can only solve the problem of addition overflow , and almost cannot solve the problem of multiplication overflow (unless there is a coincidence like multiplying by 2 and then >>>1, the high-order data is truncated and not saved), the solution is Use a larger data type to handle multiplication overflow.
Method Two:
It is easy to think of directly using mathematical methods
X*(1+X)/2≤n
X+X2 ≤ 2n
Here we will use the matching method
4X+ 4X2 ≤ 4*2*n
(2X + 1) 2 - 1 ≤ 8n
2X + 1 ≤
X ≤
Write in code:
class Solution { public int arrangeCoins(int n) { double t = 8.0 * n + 1; // cannot be written as 8*n+1, this expression is the default int, which may exceed the int range and cause the result to be wrong, so replace it with 8.0, and the expression becomes a double type return (int)((Math.sqrt(t) - 1) / 2); } }
============================== I am a slow programmer ============= =============