【动态规划】Leetcode 279. 完全平方数【中等】

2024-04-25 13:28

本文主要是介绍【动态规划】Leetcode 279. 完全平方数【中等】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

完全平方数

给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。

示例 1:

输入:n = 12
输出:3
解释:12 = 4 + 4 + 4

解题思路

  • 1、使用动态规划求解,定义一个一维数组dp,其中dp[i]表示和为i的完全平方数的最少数量。
  • 2、初始化数组dp,长度为n + 1,全部初始化为最大值,dp[0]为0。
  • 3、对于每个数字i,遍历从1到sqrt(i)的完全平方数j*j,更新dp[i]为dp[i - j * j] + 1和dp[i]中的较小值。
    动态规划的状态转移方程为:
  •   dp[i] = min(dp[i], dp[i - j * j] + 1),其中 1 <= j * j <= i
    
    这个方程的意思是,如果当前的数 i 可以由 j * j 和 i - j * j 组成,那么 dp[i] 就可以通过 dp[i - j * j] + 1 来更新,即将 j * j 加入到和为 i 的完全平方数的组合中。
  • 4、最终返回dp[n]即可。

Java实现

public class PerfectSquares {public int numSquares(int n) {int[] dp = new int[n + 1];Arrays.fill(dp, Integer.MAX_VALUE);dp[0] = 0;/*** 首先,定义一个数组 dp[],其中 dp[i] 表示组成数值 i 的最小平方数数量。** 然后,通过两层循环遍历所有可能的数值 i,从 1 到 n。** 内层循环中,对于当前数值 i,我们尝试找到组成它的最小平方数数量。* 我们遍历所有小于等于 i 的平方数,记为 j * j,并更新 dp[i] 的值为* dp[i - j * j] + 1 的最小值。也就是说,我们找到了一个平方数 j * j,* 并尝试用它去更新 i 的最小平方数数量,看是否可以得到更优的解。** 最终,当外层循环结束时,dp[n] 中存储的就是组成数值 n 的最小平方数数量。* 这种解法的核心思想是利用动态规划的思想,* 通过计算子问题的最优解来构建更大规模问题的最优解。* 通过从小到大的顺序计算所有可能的数值 i,我们可以确保在计算 dp[i] 时,* dp[i - j * j] 已经计算过了,并且存储了正确的结果,* 从而确保每个状态的最优解被正确计算出来。*/for (int i = 1; i <= n; i++) {for (int j = 1; j * j <= i; j++) {dp[i] = Math.min(dp[i], dp[i - j * j] + 1);}}return dp[n];}public static void main(String[] args) {PerfectSquares ps = new PerfectSquares();int n = 12;System.out.println("Minimum number of perfect squares: " +ps.numSquares(n)); // Output: 3 (12 = 4 + 4 + 4)}
}

时间空间复杂度

  • 时间复杂度:外层循环遍历了n次,内层循环遍历了sqrt(n)次,时间复杂度为O(n * sqrt(n))。

  • 空间复杂度:使用了长度为n + 1的数组dp,空间复杂度为O(n)。

这篇关于【动态规划】Leetcode 279. 完全平方数【中等】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/934811

相关文章

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

动态规划---打家劫舍

题目: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路: 动态规划五部曲: 1.确定dp数组及含义 dp数组是一维数组,dp[i]代表

软考系统规划与管理师考试证书含金量高吗?

2024年软考系统规划与管理师考试报名时间节点: 报名时间:2024年上半年软考将于3月中旬陆续开始报名 考试时间:上半年5月25日到28日,下半年11月9日到12日 分数线:所有科目成绩均须达到45分以上(包括45分)方可通过考试 成绩查询:可在“中国计算机技术职业资格网”上查询软考成绩 出成绩时间:预计在11月左右 证书领取时间:一般在考试成绩公布后3~4个月,各地领取时间有所不同

poj 2976 分数规划二分贪心(部分对总体的贡献度) poj 3111

poj 2976: 题意: 在n场考试中,每场考试共有b题,答对的题目有a题。 允许去掉k场考试,求能达到的最高正确率是多少。 解析: 假设已知准确率为x,则每场考试对于准确率的贡献值为: a - b * x,将贡献值大的排序排在前面舍弃掉后k个。 然后二分x就行了。 代码: #include <iostream>#include <cstdio>#incl

HDU 2159 二维完全背包

FATE 最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务。久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完这最后一级。现在的问题是,xhd升掉最后一级还需n的经验值,xhd还留有m的忍耐度,每杀一个怪xhd会得到相应的经验,并减掉相应的忍耐度。当忍耐度降到0或者0以下时,xhd就不会玩这游戏。xhd还说了他最多只杀s只怪。请问他能

zoj 1721 判断2条线段(完全)相交

给出起点,终点,与一些障碍线段。 求起点到终点的最短路。 枚举2点的距离,然后最短路。 2点可达条件:没有线段与这2点所构成的线段(完全)相交。 const double eps = 1e-8 ;double add(double x , double y){if(fabs(x+y) < eps*(fabs(x) + fabs(y))) return 0 ;return x + y ;

代码随想录冲冲冲 Day39 动态规划Part7

198. 打家劫舍 dp数组的意义是在第i位的时候偷的最大钱数是多少 如果nums的size为0 总价值当然就是0 如果nums的size为1 总价值是nums[0] 遍历顺序就是从小到大遍历 之后是递推公式 对于dp[i]的最大价值来说有两种可能 1.偷第i个 那么最大价值就是dp[i-2]+nums[i] 2.不偷第i个 那么价值就是dp[i-1] 之后取这两个的最大值就是d

leetcode-24Swap Nodes in Pairs

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode swapPairs(L

leetcode-23Merge k Sorted Lists

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode mergeKLists