/*
难度:中等
给定正整数n,找到若干完全平方数,使得它们的和等于n,并且完全平方数的个数最少。
示例:
输入 n=12
输出 3
12 = 4 + 4 + 4
输入 n=13
输出 2
13 = 4 + 9
假定:1 <= n <= 10000
*/
extension Daily {
static func test_leetcode279() {
let n = 4308
let start = Date()
print(start)
let res = Daily.leetcode279(n)
print(Date().timeIntervalSince(start))
print("最终结果 \(res)")
}
static func leetcode279(_ n: Int) -> Int {
if n < 1 || n > 10000 {
print("n is invalid")
return 0
}
var max = Int(sqrt(Double(n)));
if max * max == n {
print("n 是完全平方数, \(max)")
return 1
}
let squares = [0,1,4,9,16,25,36,49,64,81,100,121,144,169,196,225,256,289,324,361,400,441,484,
529,576,625,676,729,784,841,900,961,1024,1089,1156,1225,1296,1369,1444,1521,
1600,1681,1764,1849,1936,2025,2116,2209,2304,2401,2500,2601,2704,2809,2916,
3025,3136,3249,3364,3481,3600,3721,3844,3969,4096,4225,4356,4489,4624,4761,
4900,5041,5184,5329,5476,5625,5776,5929,6084,6241,6400,6561,6724,6889,7056,
7225,7396,7569,7744,7921,8100,8281,8464,8649,8836,9025,9216,9409,9604,9801,10000]
max += 1
let cols = max*max + 1
var line = Array(repeating: 0, count: cols );
for idx in 1..<line.count {
line[idx] = idx
}
for idx in 1...max {
line[squares[idx]] = 1;
if idx < max {
line[squares[idx]+1] = 2;
}
}
aloop: for idx in 2...max {
let pre = squares[idx-1]
var times = 1
var xxx = pre
for j in stride(from: pre, through: n, by: pre) {
for sidx in 0..<pre {
let ridx = j + sidx
if ridx > n {
break
}
if line[ridx] == 1 || line[ridx] == 2 {
continue
}
let tran = line[ridx - xxx] + times
if tran < line[ridx] {
line[ridx] = tran
}
}
times += 1
xxx += pre
if idx == max && j == n {
break aloop
}
}
}
return line[n]
}
}
08-18
10-11
301