leetcode之动态规划的面试题


1.连续子数组的最大和

输入一个长度为n的整型数组array,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。

数据范围: 1 <= n <= 10^51<=n<=105
-100 <= a[i] <= 100?100<=a[i]<=100
要求:时间复杂度为 O(n),空间复杂度为 O(n)
进阶:时间复杂度为 O(n),空间复杂度为 O(1)

有以下几种方法:

方法一:暴力方法,从分别以数组的每个节点为起点,计算出从该起点到末尾的最大值;

 1 public class Solution {
 2     public int FindGreatestSumOfSubArray(int[] array) {
 3         int max = Integer.MIN_VALUE;
 4         for(int i = 0; i < array.length; i++){
 5             int sum = lengthOfsubArray(array, i);
 6             if(max < sum){
 7                 max = sum;
 8             }
 9         }
10         return max;
11     }
12     
13     public  int lengthOfsubArray(int[] arr, int startNum){
14         int max = Integer.MIN_VALUE;
15         int sum = 0;
16         for(int i = startNum; i < arr.length; i++){
17             sum += arr[i];
18             if(sum > max){
19                 max = sum;
20             }
21         }
22         return max;
23     }
24 }

该方法可能会超时;

方法二:采用动态规划的方法,创建dp[]数组;

dp[i] = Math.max(dp[i-1]+array[i], array[i]);

 1 public class Solution {
 2     public int FindGreatestSumOfSubArray(int[] array) {
 3         int length = array.length;
 4         int[] dp = new int[length];
 5         int max = array[0];
 6         dp[0] = array[0];
 7         for(int i = 1; i < length; i++){
 8             if(dp[i-1] + array[i] > array[i]){
 9                 dp[i] = dp[i-1]+array[i];
10             }else{
11                 dp[i]=array[i];
12             }
13             if(max<dp[i]){
14                 max=dp[i];
15             }
16         }
17         return max;
18     }
19 }

2.连续子数组的最大和(二)

输入一个长度为n的整型数组array,数组中的一个或连续多个整数组成一个子数组,找到一个具有最大和的连续子数组。 1.子数组是连续的,比如[1,3,5,7,9]的子数组有[1,3],[3,5,7]等等,但是[1,3,7]不是子数组 2.如果存在多个最大和的连续子数组,那么返回其中长度最长的,该题数据保证这个最长的只存在一个 3.该题定义的子数组的最小长度为1,不存在为空的子数组,即不存在[]是某个数组的子数组 4.返回的数组不计入空间复杂度计算   数据范围: 1<=n<=10^51<=n<=105
-100 <= a[i] <= 100?100<=a[i]<=100
  要求:时间复杂度O(n),空间复杂度O(n)
进阶:时间复杂度O(n),空间复杂度O(1)
有以下几种方法; 方法一:采用暴力方法,两次循环获取连续子数组最大和;
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param array int整型一维数组 
     * @return int整型一维数组
     */
    public int[] FindGreatestSumOfSubArray (int[] array) {
        int max=Integer.MIN_VALUE;
        int sum=0;
        int startNum=0;
        int endNum=0;
        int length=0;
        for(int i=0;imax){
                    max=sum;
                    startNum=i;
                    endNum=j;
                    length=endNum-startNum+1;
                }else if(sum == max && length


 
方法二:方法和上题一样,采用动态规划的算法;
 

 1 import java.util.*;
 2 
 3 
 4 public class Solution {
 5     /**
 6      * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 7      *
 8      * 
 9      * @param array int整型一维数组 
10      * @return int整型一维数组
11      */
12     public int[] FindGreatestSumOfSubArray (int[] array) {
13         int[] dp = new int[array.length];
14         dp[0] = array[0];
15         int maxEndIndex=0;
16         int max=dp[0];
17         ArrayList maxEndIndexArr = new ArrayList<>();
18         for(int i=1;i){
19             if(dp[i-1]+array[i]>array[i]){
20                 dp[i]=dp[i-1]+array[i];
21             }else{
22                 dp[i]=array[i];
23             }
24             if(max<=dp[i]){
25                 max=dp[i];
26                 maxEndIndex=i;
27             }
28         }
29         //收集所有的最大值的末尾索引
30         for(int i=0; i<=maxEndIndex;i++){
31             if(dp[i] == max){
32                 maxEndIndexArr.add(i);
33             }
34         }
35         int startIndex = 0;
36         int maxLength = 0;
37         for(Integer m:maxEndIndexArr){
38             int tempMax=max;
39             int tempStartIndex=m;
40             for(int i=m;i>=0;i--){
41                 tempMax = tempMax - array[i];
42                 if(tempMax==0){
43                     tempStartIndex=i;
44                 }
45             }
46             if(maxLength){
47                 maxLength=m-tempStartIndex+1;
48                 startIndex=tempStartIndex;
49                 maxEndIndex=m;
50             }
51         }
52         int[] result = new int[maxEndIndex-startIndex+1];
53         for(int i=0;i){
54             result[i]=array[i+startIndex];
55         }
56         return result;
57     }
58 }
3. 跳台阶   一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个 n 级的台阶总共有多少种跳法(先后次序不同算不同的结果)。 数据范围:0n40 要求:时间复杂度:O(n) ,空间复杂度:O(1)
有以下几种求解方法: 方法一:递归方法;
public class Solution {
    public int jumpFloor(int target) {
        if(target==1){
            return 1;
        }else if(target==2){
            return 2;
        }else{
            return jumpFloor(target-1) + jumpFloor(target-2);
        }
    }
}
  方法二:动态规划的方式,创建数组dp[],递推公式如下: dp[1]=1,dp[2]=2; dp[n]=dp[n-1]+dp[n-2];
public class Solution {
    public int jumpFloor(int target) {
        if(target==1||target==2){
            return target;
        }
        int[] dp = new int[target+1];
        dp[1] = 1;
        dp[2] = 2;
        for(int i=3;i<=target;i++){
            dp[i]=dp[i-1]+dp[i-2];
        }
        return dp[target];
    }
}
  4.斐波那契数列  和3的跳台阶一直,代码基本相似,都可以利用动态规划和递归的方式进行编写;   5.正则表达式匹配 请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配 数据范围: (1).str 可能为空,且只包含从 a-z 的小写字母。 (2).pattern 可能为空,且只包含从 a-z 的小写字母以及字符 . 和 *,无连续的 '*'。 (3).1 <= str.length <= 20 (4).1 <= pattern.length <= 30 要求:空间复杂度 O(1),时间复杂度 O(n)