题目描述
给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。
完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。
解题思路
- 动态规划:
- 定义
dp[i]表示和为i的最少完全平方数个数 - 初始化
dp = 0(边界条件) - 状态转移:
dp[i] = min(dp[i], dp[i - j*j] + 1)(j为平方数,1 ≤ j ≤ √i)
- 定义
- 数学优化:
- 基于四平方和定理:任何正整数可表示为4个平方数和
- 特殊处理:若
n是完全平方数,直接返回1
- BFS剪枝:
- 将问题转化为层级遍历(0→n的最短路径)
- 每层减去平方数,首次到达0的层级即解
关键洞察
- 子问题重叠:
- 大数解依赖小数解(如
dp=dp+1=dp+3) - 动态规划自然复用子问题解
- 大数解依赖小数解(如
- 平方数边界:
- 只需考虑
j*j ≤ i的平方数 - 内层循环可优化为
j=1→√i
- 只需考虑
- 四平方和定理:
- 解仅可能为1/2/3/4四种情况
- 若
n=4^k*(8m+7)则解为4
- BFS层级特性:
- 每层表示当前剩余数值
- 减平方数操作等价于边权为1的图搜索
复杂度分析
| 方法 | 时间复杂度 | 空间复杂度 |
|---|---|---|
| 动态规划 | O(n√n) | O(n) |
| BFS | O(n)(最坏情况) | O(n) |
| 数学法 | O(√n) | O(1) |
注:n为输入正整数,√n表示平方根取整
代码实现
- 动态规划
var numSquares = function (n) {
// 创建动态规划数组,dp[i] 表示和为 i 的最少完全平方数数量
const dp = new Array(n + 1).fill(Infinity);
dp[0] = 0; // 基础情况:和为 0 需要 0 个平方数
// 预先计算所有可能用到的平方数
const squares = [];
for (let i = 1; i * i <= n; i++) {
squares.push(i * i);
}
// 动态规划填充过程
for (let i = 1; i <= n; i++) {
for (const square of squares) {
if (square > i) break; // 平方数大于当前值,提前终止
dp[i] = Math.min(dp[i], dp[i - square] + 1);
}
}
return dp[n];
};
- BFS
/**
* @param {number} n
* @return {number}
*/
const numSquares = (n) => {
const queue = [n];
const visited = new Set([n]);
let level = 0;
while (queue.length) {
level++;
const size = queue.length;
for (let i = 0; i < size; i++) {
const cur = queue.shift();
for (let j = 1; j * j <= cur; j++) {
const next = cur - j * j;
if (next === 0) return level;
if (!visited.has(next)) {
visited.add(next);
queue.push(next);
}
}
}
}
return level;
};
- 数学法
/**
* @param {number} n
* @return {number}
*/
const numSquares = (n) => {
// 检测是否为完全平方数
const isSquare = (x) => Math.floor(Math.sqrt(x)) ** 2 === x;
// 情况1:n为完全平方数
if (isSquare(n)) return 1;
// 情况2:检查是否存在 a^2+b^2=n
for (let i = 1; i * i <= n; i++) {
if (isSquare(n - i * i)) return 2;
}
// 情况3:四平方和定理特殊情况
while (n % 4 === 0) n /= 4;
if (n % 8 === 7) return 4;
// 其他情况为3
return 3;
};
实际应用场景
- 图像压缩:将图像块表示为平方和优化存储`
- 密码学:有限域平方和分解`
- 物理建模:能量量子化表示`
- 金融拆分:资产单位最小化分割`