【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),只使用了常數個數的存儲空間。