leeched-day3
今天的都是用动态规划解决的。
53最大子数组和
题目描述:给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组 是数组中的一个连续部分。
印象中这道题做过,但是我还是不会,看了题解,然后自己分析了的结果如下。
这道题需要求的是连续子数组的最大和,有两个关键点,第一个是连续,第二个是最大和。我们在规定状态转移方程的时候,对于一个dp[i]
,我们所定义的是:dp[i]
代表以第i个下标结尾的所对应的连续子数组的最大和,我们确定了在dp[i]
时,第i个下标对应的元素是必须选到的。所以我们需要考虑的就是dp[i-1]
和nums[i]
的问题。
也就是说,因为nums[i]
是必须选到的,我们只需要考虑它nums[i]
本身的值与它之前的连续子数组的值加上它本身谁更大,即,我们的dp[i]的值就是Max{nums[i],dp[i-1]+nums[i]}
。然后对于这个dp,我们看看初始值,对于第一个元素,最大连续子数组就是它本身,也就是dp[0]=nums[0]
,从第二个元素开始,就可以使用上述状态转移方程。
关键代码
for(int i = 1;i< nums.length;i++){
dp[i] = Math.max(nums[i],nums[i]+dp[i-1]);
}
求完dp后,再使用一个遍历dp找到最大的连续子数组的值。
使用动态规划,时间复杂度在O(n),因为其实相当于进行了两个遍历,第一个是求dp,第二个是最大。
(这题听说还可以用分治,留个坑)
70爬楼梯
题目描述:假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
思路:每次可以爬1或者2个台阶,那么爬到第一个台阶就有1种方法;爬到第二个台阶有两种方法,分别是1+1和2;爬到第三个台阶有两种选择三种方法,分别是从第一个台阶开始爬两阶也就是1+2,和从第二个台阶开始爬一阶,也就是1+1+1,2+1,其实就是相当于,爬到第i个台阶了,就有两种选择,第一种是从第i-1个台阶,再爬1阶,第二种是从第i-2个台阶爬两阶。所以爬到第i个台阶的方法和就是爬到第i-1个台阶的方法和加上爬到第i-2个台阶的方法和。
也就是说,我们的dp[i]
定义为爬到i的的方法数,我们的状态转移方程为dp[i]=dp[i-1]+dp[i-2]
,初始值dp[0]=1,dp[1]=2
.关键代码为
for(int i = 2;i<n;i++){
dp[i] = dp[i-1]+dp[i-2];
}
746使用最小花费爬楼梯
题目描述:给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。请你计算并返回达到楼梯顶部的最低花费。
思路:这题和上面那题有点类似,只是多加了一个费用,我们这里dp也可以设置为爬到第i阶时所花费的最小的费用。充分理解题意后我们可以知道dp[0]=0,dp[1]=0。然后第i个台阶怎么才能得到最小的费用呢?我们知道其实它有两种爬楼梯方法,第一种是从i-1阶爬1阶上来,第二种是从i-2爬两阶上来,所有我们到第i阶的最小费用就是 从第i-1阶的最小费用加上i-1阶爬上来的花费 和 从i-2阶爬上来的费用加上爬到它的最小费用 中的最小费用。也就是说,我们的状态转移方程是dp[i]=max(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2])
关键代码
for(int i = 2;i<len;i++){
dp[i] = Math.min(dp[i-2]+cost[i-2],dp[i-1]+cost[i-1]);
}
最后return Math.min(dp[len-1]+cost[len-1],dp[len-2]+cost[len-2]);
因为要爬到顶端,所以还要爬一步。
1.两数之和
这个之前写过 用hashmap,不再写。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了