【Leetcode 热题 100】279. 完全平方数

server/2025/1/24 9:53:32/

问题背景

给你一个整数 n n n,返回 和为 n n n 的完全平方数的最少数量 。
完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如, 1 , 4 , 9 1,4,9 1,4,9 16 16 16 都是完全平方数,而 3 3 3 11 11 11 不是。

数据约束

  • 1 ≤ n ≤ 1 0 4 1 \le n \le 10 ^ 4 1n104

解题过程

动态规划,用两个状态: i i i 表示当前枚举的完全平方数的算数平方根, j j j 表示剩余的和。
这样一来,状态转移方程就可以表示为 d f s ( i , j ) = { d f s ( i − 1 , j ) j < i 2 m i n ( d f s ( i − 1 , j ) , d f s ( j − i 2 ) + 1 ) j ≤ i 2 \ dfs(i, j) = \begin{cases} dfs(i−1,j) & j \lt i ^ 2 \\ min(dfs(i - 1, j), dfs(j - i ^ 2) + 1) & j \le i ^ 2 \\ \end{cases}  dfs(i,j)={dfs(i1,j)min(dfs(i1,j),dfs(ji2)+1)j<i2ji2
递归入口 d f s ( ⌊ n ⌋ , n ) dfs(\lfloor \sqrt n \rfloor, n) dfs(⌊n ,n),表示初始枚举的最大数为 n \sqrt n n ,剩余的和为 n n n
递归边界 d f s ( 0 , 0 ) = 0 dfs(0, 0) = 0 dfs(0,0)=0,表示没有剩余的数可选,且和刚好为零。

翻译成递推之后,由于计算时只用到前一个状态,记忆化数组可以去掉一个维度。
递推的计算可以放在静态代码块里,给所有测试用例公用。

具体实现

递归

class Solution {private static final int[][] memo = new int[110][10010];static {for (int[] row : memo) {Arrays.fill(row, -1);}}public int numSquares(int n) {return dfs((int) Math.sqrt(n), n);        }private int dfs(int i, int j) {if (i == 0) {return j == 0 ? 0 : Integer.MAX_VALUE;}if (memo[i][j] != -1) {return memo[i][j];}if (j < i * i) {return memo[i][j] = dfs(i - 1, j);}return memo[i][j] = Math.min(dfs(i - 1, j), dfs(i, j - i * i) + 1); }
}

递推

class Solution {private static final int MAX_N = 10000;private static final int[][] dp = new int[110][MAX_N + 1];static {Arrays.fill(dp[0], Integer.MAX_VALUE);dp[0][0] = 0;for (int i = 1; i * i <= MAX_N; i++) {for (int j = 0; j <= MAX_N; j++) {if (j < i * i) {dp[i][j] = dp[i - 1][j];} else {dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - i * i] + 1);}}}}public int numSquares(int n) {return dp[(int) Math.sqrt(n)][n];    }
}

空间优化

class Solution {private static final int MAX_N = 10000;private static final int[] dp = new int[MAX_N + 1];static {Arrays.fill(dp, Integer.MAX_VALUE);dp[0] = 0;for (int i = 1; i * i <= MAX_N; i++) {for (int j = i * i; j <= MAX_N; j++) {dp[j] = Math.min(dp[j], dp[j - i * i] + 1);}}}public int numSquares(int n) {return dp[n];    }
}

http://www.ppmy.cn/server/160991.html

相关文章

左叶子之和(力扣404)

这道题需要将左右子树的左叶子结点之和不断返回给该左右子树的父节点&#xff0c;这是典型的后序遍历。如果大家对于二叉树的遍历不熟悉的话&#xff0c;可以先去看一下我的关于二叉树遍历的博客。否则直接看这道题是很容易懵逼的。熟悉了二叉树的遍历之后&#xff0c;大家可以…

ssm基于HTML5的红酒信息分享系统

SSM基于HTML5的红酒信息分享系统是一个专注于红酒领域的综合性信息平台&#xff0c;旨在为红酒爱好者、从业者以及普通消费者提供一个便捷的交流与获取红酒相关信息的空间。 一、系统背景与意义 随着人们生活水平的提高和消费观念的转变&#xff0c;红酒作为一种高雅的饮品&a…

一文了解树与森林基础

文章目录 树和森林1树的存储结构1.1双亲表示法1.2孩子表示法1.3孩子兄弟表示法 2树、森林与二叉树的转换2.1森林与二叉树的转换2.2 树与二叉树的转换 3树和森林的遍历3.1树的遍历3.2森林的遍历3.3 树和森林的遍历与二叉树的遍历关系 4树的应用——并查集4.1并查集及其相关操作4…

不使用 JS 纯 CSS 获取屏幕宽高

前言 在现代前端开发中&#xff0c;获取屏幕的宽度和高度通常依赖于 JavaScript。然而现代 CSS 也可以获取到屏幕的宽高&#xff0c;通过自定义属性&#xff08;CSS Variables&#xff09;和一些数学函数来实现这一目标。本文将详细解析如何使用 CSS 的 property 规则和一些数…

SpringBoot整合RabbitMQ

RabbitMQ 简介 消息中间件&#xff1a;它接收消息并且转发&#xff0c;就类似于一个快递站&#xff0c;卖家把快递通过快递站&#xff0c;送到我们的手上&#xff0c;MQ也是这样&#xff0c;接收并存储消息&#xff0c;再转发。 RabbitMQ在 2007 年由Rabbit科技有限公司发布&a…

C语言-运算符

1. 按位与运算符&#xff08;&&#xff09; 按位与运算符对两个整数的每一位执行“与”操作。只有当两个相应位都为 1 时&#xff0c;结果才为 1 &#xff1b;否则为 0。 // 示例 int a 5; // 二进制: 0101 int b 3; // 二进制: 0011 int result a & b; …

vue + element-ui 组件样式缺失导致没有效果

失效 代码&#xff1a; 修改方法&#xff1a; 在main.js文件里面加上&#xff1a; import element-ui/lib/theme-chalk/index.css; 最后&#xff1a;

【行空板K10】项目实践案例征集 跨学科案例 研究蒸发量

目录 项目来源 项目简介 项目知识点 项目原理 物联网硬件架构 硬件简介 硬件接线原理 硬件接线实物 实验流程 实验注意事项 程序截图 项目数据表 总结 本文首发于DF创客社区&#xff1a;项目实践案例征集 跨学科案例 行空板K10 研究蒸发量 DF创客社区https://mc.d…