几种最长XX类型的动态规划题目

19 篇文章 0 订阅
11 篇文章 0 订阅
无重复最长子数组

遍历数组,每到一个新的位置i就看这个数字在之前是否出现过,如果没出现过直接dp[i] = dp[i-1] + 1,如果出现过,就看看i和之前出现过的位置的距离d是否比dp[i-1]大,要是大依然dp[i] = dp[i-1] + 1,(如 ayxyza,第二个a出现的位置下标是5,第一个a下标是0,相减等于5,而dp[4]=3,所以可以把这个a算进来);但如果d比dp[i-1]小,那么dp[i]就只能是d了(如abcb,b第一次是1,第二次是3,d=3-1=2,而dp[2]=3,所以dp[3]只能是2,即cb)。

public int maxLength (int[] arr) {
    // write code here
    HashMap<Integer, Integer> map = new HashMap<>();
    
    int[] dp = new int[arr.length];
    dp[0] = 1;
    map.put(arr[0], 0);
    int max = dp[0];
    for (int i = 1; i < arr.length; i++) {
        if (!map.containsKey(arr[i])) {
            dp[i] = dp[i-1] + 1;
            map.put(arr[i], i);
        }else {
            int index = map.get(arr[i]);
            if (i - index <= dp[i-1]) {
                dp[i] = i - index;
            }else {
                dp[i] = dp[i-1] + 1;
            }
            map.put(arr[i], i);
        }
        max = Math.max(max, dp[i]);
    }
    return max;
}
最长回文子串

在这里插入图片描述

public int getLongestPalindrome(String A, int n) {
    // write code here
    if (n < 2) return A.length();
    
    boolean[][] dp = new boolean[n][n];
    int max = 0;
    for (int i = 1; i < n; i++) {
        for (int j = 0; j < i; j++) {
            if (A.charAt(i) != A.charAt(j)) continue;
            
            if (j == i || i - j <= 2) dp[j][i] = true;
            else {
                dp[j][i] = dp[j+1][i-1];
            }
            
            if (dp[j][i] && i - j + 1 > max) {
                max = Math.max(max, i - j + 1);
            }
        }
    }
    return max;
}
最长递增子序列

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
解法1: 定义dp数组,dp[i]代表i位置的最长自增子序列,到i+1时,遍历从0到i,如果对应位置的元素小于i+1位置,那么就尝试dp[i+1] = max(dp[i+1], dp[0到i])。

public int lengthOfLIS(int[] arr) {
    if (arr == null || arr.length == 0) return 0;
    int n = arr.length;
    int[] dp = new int[n];
    int res = 0;
    Arrays.fill(dp, 1);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < i; j++) {
            if (arr[j] < arr[i]) {
                dp[i] = Math.max(dp[i], dp[j]+1);
            }
        }
        res = Math.max(res, dp[i]);
    }
    return res;
}

解法2:使用二分法,https://leetcode-cn.com/problems/longest-increasing-subsequence/solution/zui-chang-shang-sheng-zi-xu-lie-dong-tai-gui-hua-2/

public int[] LIS (int[] arr) {
        // write code here
        if (arr == null || arr.length == 0) return new int[0];
        int n = arr.length;
        int[] dp = new int[n];
        int[] end = new int[n];
        int index = 0;
        
        end[0] = arr[0];
        
        for (int i = 1; i < n; i++) {
            if (end[index] < arr[i]) {
                end[++index] = arr[i];
                dp[i] = index;
            }else {
                int left = 0, right = index;
                while (left <= right) {
                    int mid = left +((right - left) >> 1);
                    if (end[mid] < arr[i]) {
                        left = mid + 1;
                    }else {
                        right = mid - 1;
                    }
                }
                end[left] = arr[i];
                dp[i] = left;
            }
        }
        
        int[] res = new int[index+1];
        for (int i = n-1; i >= 0; i--) {
            if (dp[i] == index) {
                res[index--] = arr[i];
            }
        }
        return res;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值