一、JZ42 连续子数组的最大和(简单)
动态规划,设动态规划列表 dp,dp[i] 代表以元素 array[i] 为结尾的连续子数组最大和。状态转移方程: dp[i] = Math.max(dp[i-1]+array[i], array[i])
具体思路如下:
1.遍历数组,比较 dp[i-1] + array[i] 和 array[i]的大小;
2.为了保证子数组的和最大,每次比较 sum 都取两者的最大值;
3.用max变量记录计算过程中产生的最大的连续和dp[i];
public int FindGreatestSumOfSubArray(int[] array) {
int sum = 0;
int max = array[0];
for(int i=0;i<array.length;i++){
// 优化动态规划,确定sum的最大值
sum = Math.max(sum + array[i], array[i]);
// 每次比较,保存出现的最大值
max = Math.max(max,sum);
}
return max;
}
二、JZ85 连续子数组的最大和(二)(中等)
1、动态规划
import java.util.*;
public class Solution {
/**
* @param array int整型一维数组
* @return int整型一维数组
*/
public int[] FindGreatestSumOfSubArray (int[] array) {
// write code here
if(array.length == 1) return array;
int sum = 0;
int max = array[0];
//子数组区间
int left = 0;
int right = -1;
//记录最长区间
int start = 0;
int end = 0;
for (int item : array) {
right ++;
if (sum + item < item ) {
left = right;
}
sum = Math.max(sum + item, item);
//找到更大或更长的子数组就更新值
if (sum > max || sum == max && (right - left) > (end - start)) {
max = sum;
start = left;
end = right;
}
}
int[] result = new int[end - start + 1];
int i = 0;
while (start <= end) {
result[i] = array[start];
i++;
start ++;
}
return result;
}
}
三、JZ69 跳台阶(简单)
1、动态规划
public class Solution {
public int jumpFloor(int target) {
if(target == 0 || target == 1) return 1;
if(target == 2) return 2;
int number1 = 1, number2 = 2;
for(int i =3;i<= target;i++) {
if(i%2 == 1) {
number1 += number2;
} else {
number2 += number1;
}
}
return (target)%2 ==1 ? number1 : number2;
}
}
2、递归
public class Solution {
public int jumpFloor(int target) {
//这里第0项为1,第1项为1
if(target <= 1)
return 1;
else
//递归子问题相加
return jumpFloor(target - 1) + jumpFloor(target - 2);
}
}
四、JZ10 斐波那契数列(简单,跟第三题代码非常相似)
动态规划
public class Solution {
public int jumpFloor(int target) {
if(target == 0 || target == 1) return 1;
if(target == 2) return 2;
int number1 = 1, number2 = 2;
for(int i =3;i<= target;i++) {
if(i%2 == 1) {
number1 += number2;
} else {
number2 += number1;
}
}
return (target)%2 ==1 ? number1 : number2;
}
}
2、递归
public class Solution {
public int jumpFloor(int target) {
//这里第1项为1,第2项为1
if(target <= 2)
return 1;
else
//递归子问题相加
return jumpFloor(target - 1) + jumpFloor(target - 2);
}
}
五、JZ19 正则表达式匹配(较难)
1、解题思路:
假设主串为 str,模式串为 pattern 从最后一步出发,需要关注最后进来的字符。假设 str 的长度为 n ,pattern的长度为 m ,关注正则表达式 pattern的最后一个字符是谁,它有三种可能,正常字符、'*' 和 '.'(点),那针对这三种情况讨论即可,如下:
1、如果 pattern的最后一个字符是正常字符,那就是看str[n−1] 是否等于 pattern[m−1],相等则看str [0..n−2]与 pattern [0..m−2],不等则是不能匹配,这就是子问题。
2、如果 pattern 的最后一个字符是 ‘.’,它能匹配任意字符,直接看 str [0..n−2]与 pattern [0..m−2]
3、如果 pattern 的最后一个字符是‘*’,它代表 pattern[m-2]=c 可以重复0次或多次,它们是一个整体 c*
情况一:str[n-1] 是 0 个 c,pattern最后两个字符废了,能否匹配取决于 str [0..n−1]和 pattern [0..m−3]是否匹配
情况二:str[n-1] 是多个 c 中的最后一个(这种情况必须 str[n-1]=c 或者 c='.'),所以str 匹配完往前挪一个,pattern 继续匹配,因为可以匹配多个,继续看str[0..n−2]和 pattern[0..m−1]是否匹配。
转移方程
f[i][j] 代表 str 的前 i 个和 pattern 的前 j 个能否匹配
对于前面两个情况,可以合并成一种情况 f[i][j]=f[i−1][j−1]
对于第三种情况,对于 c* 分为看和不看两种情况
不看:直接砍掉正则串pattern 的后面两个, f[i][j]=f[i][j−2]
看:正则串pattern 不动,主串str前移一个,f[i][j]=f[i−1][j]
初始条件
特判:需要考虑空串空正则
空串和空正则是匹配的,f[0][0]=true
空串和非空正则,不能直接定义 true 和 false,必须要计算出来。(比如str= '' '' ,pattern=a*b*c*)
非空串和空正则必不匹配,f[1][0]=...=f[n][0]=false
非空串和非空正则,那肯定是需要计算的了。
大体上可以分为空正则和非空正则两种,空正则也是比较好处理的,对非空正则我们肯定需要计算,非空正则的三种情况,前面两种可以合并到一起讨论,第三种情况是单独一种,那么也就是分为当前位置是 '*' 和不是 '*' 两种情况了。
结果
我们开数组要开 n+1 ,这样对于空串的处理十分方便。结果就是 f[n][m]
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param str string字符串
* @param pattern string字符串
* @return bool布尔型
*/
public boolean match (String str, String pattern) {
// write code here
int n = str.length();
int m = pattern.length();
boolean[][] f =new boolean[n + 1][m + 1];
for(int i= 0;i<=n;i++) {
for(int j=0;j<=m;j++) {
//分成空正则和非空正则两种
if(j == 0) {
f[i][j] = i == 0;
} else {
//非空正则分为两种情况 * 和 非*
if(pattern.charAt(j - 1) != '*') {
if(i > 0 && (str.charAt(i -1) == pattern.charAt(j-1) || pattern.charAt(j-1) == '.')) {
f[i][j] = f[i -1][j-1];
}
} else {
//碰到 * 了,分为看和不看两种情况
//不看
if(j >= 2) {
f[i][j] |= f[i][j-2];
}
//看
if(i >= 1 && j >= 2 && (str.charAt(i -1) == pattern.charAt(j -2) || pattern.charAt(j -2) == '.')) {
f[i][j] |= f[i-1][j];
}
}
}
}
}
return f[n][m];
}
}
六、JZ71 跳台阶扩展问题(简单)
1、动态规划
![](https://img-blog.csdnimg.cn/img_convert/7818062f9bed684037cba47ec4f604b5.png)
public class Solution {
public int jumpFloorII(int target) {
if(target == 0 || target == 1) return 1;
int result = 1;
for(int i = 2;i<=target;i++) {
result *= 2;
}
return result;
}
}
2、递归
public class Solution {
public int jumpFloorII(int target) {
//1或0都是1种
if(target <= 1)
return 1;
//f(n) = 2*f(n-1)
return 2 * jumpFloorII(target - 1);
}
}
七、JZ70 矩形覆盖(中等)
1、动态规划
public class Solution {
public int rectCover(int target) {
if(target == 0) return 0;
if(target == 1) return 1;
if(target == 2) return 2;
int number1= 1, number2 = 2;
for(int i = 3;i<= target;i++){
if(i%2 == 1) {
number1 += number2;
} else {
number2 += number1;
}
}
return target%2 == 1 ? number1 : number2;
}
}
2、递归
class Solution {
public:
int rectCover(int number) {
if(number < 1){
return 0;
}else if(number <= 2){
return number;
}else{
return rectCover(number-1) + rectCover(number-2);//
}
}
};
八、JZ63 买卖股票的最好时机(一)(简单)
1、一次遍历,不断更新最低价格与当天卖出的最大利润
import java.util.*;
public class Solution {
/**
*
* @param prices int整型一维数组
* @return int整型
*/
public int maxProfit (int[] prices) {
// write code here
if(prices.length == 0 || prices.length == 1) return 0;
int min = prices[0];
int count = 0;
for(int i=1;i< prices.length;i++) {
min = Math.min(prices[i], min);
count = Math.max(prices[i] - min, count);
}
return count;
}
}
九、JZ47 礼物的最大价值(中等)
1、动态规划
import java.util.*;
public class Solution {
public int maxValue (int[][] grid) {
int m = grid.length;
int n = grid[0].length;
//第一列只能来自上方
for(int i = 1; i < m; i++)
grid[i][0] += grid[i - 1][0];
//第一行只能来自左边
for(int i = 1; i < n; i++)
grid[0][i] += grid[0][i - 1];
//遍历后续每一个位置
for(int i = 1; i < m; i++)
for(int j = 1; j < n; j++)
//增加来自左边的与上边的之间的较大值
grid[i][j] += Math.max(grid[i - 1][j], grid[i][j - 1]);
return grid[m - 1][n - 1];
}
}
十、JZ48 最长不含重复字符的子字符串(中等)
1、使用辅助ArrayList
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @return int整型
*/
public int lengthOfLongestSubstring (String s) {
// write code here
char[] chars= s.toCharArray();
int count = 0;
int max = 0;
List<Character> list = new ArrayList<>();
for (int i = 0; i< chars.length ;i++) {
if(i >= 1) {
list.add(chars[i-1]);
max = Math.max(max, list.size());
if(list.contains(chars[i])) {
int index = list.indexOf(chars[i]);
list = list.subList(index + 1, list.size());
} else {
max = Math.max(max, list.size() + 1);
}
} else {
max = 1;
}
}
return max;
}
}
十一、JZ46 把数字翻译成字符串(中等)
1、动态规划
![](https://img-blog.csdnimg.cn/img_convert/a4d84237764a607a50f8b2e8dd7dc552.png)
import java.util.*;
public class Solution {
public int solve (String nums) {
//排除0
if(nums.equals("0"))
return 0;
//排除只有一种可能的10 和 20
if(nums == "10" || nums == "20")
return 1;
//当0的前面不是1或2时,无法译码,0种
for(int i = 1; i < nums.length(); i++){
if(nums.charAt(i) == '0')
if(nums.charAt(i - 1) != '1' && nums.charAt(i - 1) != '2')
return 0;
}
int[] dp = new int[nums.length() + 1];
//辅助数组初始化为1
Arrays.fill(dp, 1);
for(int i = 2; i <= nums.length(); i++){
//在11-19,21-26之间的情况
if((nums.charAt(i - 2) == '1' && nums.charAt(i - 1) != '0') || (nums.charAt(i - 2) == '2' && nums.charAt(i - 1) > '0' && nums.charAt(i - 1) < '7'))
dp[i] = dp[i - 1] + dp[i - 2];
else
dp[i] = dp[i - 1];
}
return dp[nums.length()];
}
}