问题描述
小U准备了一些边长为整数的正方形巧克力板,希望选出若干块巧克力板,使它们的总面积恰好等于给定的整数n。巧克力板的周长应尽可能小。巧克力板的总面积恰好为n,而总周长为这些正方形边长的四倍和。请你帮助小U找到一个最优方案,输出最短的周长总和。
测试样例
样例1:
输入:
n = 11
输出:20
样例2:
输入:
n = 13
输出:20
样例3:
输入:
n = 25
输出:20
问题分析
这是一道贪心问题,贪心就是每一次选择局部最优,从而达到全局最优。解决贪心问题的关键在于怎么从局部最优推出全局最优,因此只需要思考清楚局部最优是什么?如何推出全局最优就可以了。针对这道问题固定巧克力版的总面积,周长要尽可能小,那么每一小块正方形的边长要尽可能大,这样巧克力板的数量会尽可能少,周长和就会最短。
具体步骤
- 初始化一个变量
res用于存储总周长。 - 使用一个循环,每次找到当前
n的最大可能正方形边长side,即side = Math.floor(Math.sqrt(n))。 - 如果
side的平方小于等于n,则减去这个正方形的面积,并累加其周长(side * 4)到res中。 - 重复上述步骤,直到
n减为 0。
代码
function solution(n) {
let res = 0;
while (n > 0) {
let side = Math.floor(Math.sqrt(n))
if (side ** 2 <= n) {
n -= side ** 2;
res += side * 4
}
}
return res;
}
最后利用豆包转成python提交,python代码如下:
import math
def solution(n):
res = 0
while n > 0:
side = int(math.sqrt(n)) # 找到当前n的最大可能正方形边长
if side ** 2 <= n:
n -= side ** 2 # 减去这个正方形的面积
res += side * 4 # 累加其周长到res中
return res
def main():
print(solution(11) == 20)
print(solution(13) == 20)
print(solution(25) == 20)
if __name__ == "__main__":
main()
算法复杂度分析
1、时间复杂度分析
在 solution 函数中,主要的操作是找到当前 n 的最大可能正方形边长 side,即 side = int(math.sqrt(n))。每次循环中,n 会减去一个正方形的面积 side ** 2,直到 n 减为 0。由于 side 是 n 的平方根,每次循环 n 至少会减去 side ** 2,因此,循环的次数大约是 O(sqrt(n))。而每次循环中计算 side 的时间复杂度是 O(1)。因此,总的时间复杂度是 O(sqrt(n))。
2、空间复杂度分析
主要变量有res和side。res用于存储总周长,占用常数空间 O(1)。side用于存储当前正方形的边长,占用常数空间 O(1)。此外,除了输入参数 n 外,函数中没有使用额外的空间。因此,总的空间复杂度是 O(1)。