Skip to content

Commit e9cc28f

Browse files
author
dai
committed
补充动态规划专题
1 parent c507efa commit e9cc28f

File tree

1 file changed

+123
-0
lines changed

1 file changed

+123
-0
lines changed

28-算法面试专题-动态规划.md

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,129 @@ public class DPExampleUtil {
124124
// 最终返回dp表的0,bag位置,就是我们暴力递归的主函数调用
125125
return dp[0][bag];
126126
}
127+
128+
129+
/**
130+
* 2、最长递增子序列问题
131+
* 问题描述:给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
132+
* 子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
133+
*
134+
* 例如:nums = [10,9,2,5,3,7,101,18], 返回结果是4。最长递增子序列是 [2,3,7,101],因此长度为 4 。
135+
**/
136+
public int lengthOfLIS(int[] nums) {
137+
if (nums.length == 0) {
138+
return 0;
139+
}
140+
int[] dp = new int[nums.length];
141+
dp[0] = 1;
142+
// 全局最大
143+
int max = 1;
144+
for (int i = 1; i < nums.length; i++) {
145+
// 默认每个元素的dp[i]都为1,表示自己形成的递增子序列
146+
dp[i] = 1;
147+
148+
149+
for (int j = 0; j < i; j++) {
150+
// 如果在当前位置的前面,存在一个比自己小的元素,该元素的dp[j]加上当前元素形成的新的dp[j] + 1比dp[i]大。更新这个dp[i]。否则不更新
151+
if (nums[i] > nums[j]) {
152+
dp[i] = Math.max(dp[i], dp[j] + 1);
153+
}
154+
}
155+
// 最上层循环,每一轮检查是否需要更新全局max
156+
max = Math.max(max, dp[i]);
157+
}
158+
return max;
159+
}
160+
161+
/**
162+
* 3、最大连续子数组的和(最大子序和)
163+
*
164+
* 问题描述:给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
165+
* 例如:nums = [-2,1,-3,4,-1,2,1,-5,4],返回6。连续子数组 [4,-1,2,1] 的和最大,为 6 。
166+
*
167+
**/
168+
public int maxSubArray(int[] nums) {
169+
if(nums == null || nums.length == 0) {
170+
return 0;
171+
}
172+
173+
int N = nums.length;
174+
// dp[i] 含义:子数组必须以i结尾的时候,所有可以得到的子数组中,最大累加和是多少?
175+
int[] dp = new int[N];
176+
dp[0] = nums[0];
177+
// 记录全局最大的子数组的和
178+
int max = dp[0];
179+
for (int i = 1; i < N; i++) {
180+
// 当前的值
181+
int p1 = nums[i];
182+
// 当前的值和上一个位置的最大和累加
183+
int p2 = nums[i] + dp[i - 1];
184+
// dp[i]等于,当前的值,和当前值与上一个位置最大和的累加,取大的
185+
dp[i] = Math.max(p1, p2);
186+
// 判断是否要更新全局最大值
187+
max = Math.max(max, dp[i]);
188+
}
189+
// 返回全局最大值
190+
return max;
191+
}
192+
193+
194+
/**
195+
* 4、打家劫舍问题
196+
*
197+
* 问题描述:你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
198+
* 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
199+
*
200+
* 示例输入:[1,2,3,1], 输出4;偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。偷窃到的最高金额 = 1 + 3 = 4 。
201+
*
202+
**/
203+
public int rob(int[] nums) {
204+
205+
if(nums == null || nums.length == 0) {
206+
return 0;
207+
}
208+
int[] dp = new int[nums.length];
209+
210+
for(int i = 0; i < nums.length; i++) {
211+
if(i == 0) {
212+
dp[0] = nums[i];
213+
}
214+
if(i == 1) {
215+
dp[1] = Math.max(dp[0], nums[i]);
216+
}
217+
if(i > 1) {
218+
dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);
219+
}
220+
}
221+
return dp[nums.length - 1];
222+
}
223+
224+
/**
225+
* 5、爬楼梯问题。
226+
*
227+
* 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
228+
* 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
229+
*
230+
**/
231+
public int climbStairs(int n) {
232+
if(n == 0) {
233+
return 0;
234+
}
235+
if(n == 1) {
236+
return 1;
237+
}
238+
if(n == 2) {
239+
return 2;
240+
}
241+
242+
int[] dp = new int[n + 1];
243+
dp[1] = 1;
244+
dp[2] = 2;
245+
for(int i = 3; i <= n ; i++) {
246+
dp[i] = dp[i-1] + dp[i-2];
247+
}
248+
return dp[n];
249+
}
127250

128251

129252
}

0 commit comments

Comments
 (0)