【LeetCode通关全记录】441. 排列硬币
题目地址:441. 排列硬币
解法1:暴力迭代(最容易实现)
本题最容易实现的办法就是设置一个计数器记录行数,每次循环给计数器加1并从总数中减去计数器的值,直到计数器的值比总数大时跳出循环。
func arrangeCoins(n int) int {
if n <= 1 {
return 1
}
m := 1
for n >= m {
n -= m
m++
}
return m - 1
}
执行用时: 8 ms(超过40%的Golang提交记录)
内存消耗: 2.2 MB(超过61%的Golang提交记录)
时间复杂度:O(n),for循环的执行次数与n成正比;
空间复杂度:O(1),只使用了常数个数的存储空间。
解法2:二分+等差数列求和(最容易想到)
看到这道题的第一反应就是等差数列求和,求和公式为(i * (i + 1)) / 2
,但是没有想到这个求和公式该怎么用于是改用解法1,把解法1写出来之后看了官方题解才明白原来本题中等差数列求和需要配合二分查找来使用。
func arrangeCoins(n int) int {
return sort.Search(n, func(i int) bool {
i++
return i * (i + 1) > 2 * n
})
}
执行用时: 4 ms(超过73%的Golang提交记录)
内存消耗: 2.2 MB(超过100%的Golang提交记录)
时间复杂度:O(logn),二分查找的时间复杂度为O(logn);
空间复杂度:O(1),只使用了常数个数的存储空间。
解法3:等差数列求和+求根公式(效率最高)
这种解法是从官方题解中看到的,详细解法可以看官方题解,大概就是使用等差数列求和公式列方程并解一元二次方程。不得不说这是一种十分聪明的解法,明明是初中数学知识结果很难想到可以应用在这道题里
func arrangeCoins(n int) int {
return int((math.Sqrt(float64(8*n + 1)) - 1) / 2)
}
执行用时: 0 ms(超过100%的Golang提交记录)
内存消耗: 2.2 MB(超过99.25%的Golang提交记录)
时间复杂度:O(1),不考虑math.Sqrt()
函数的内部实现的话该算法的执行效率不受问题规模的影响;
空间复杂度:O(1),只使用了常数个数的存储空间。