LeetCode --- 300. 最长上升子序列

给定一个无序的整数序列,求出它最长上升子序列的长度(要求严格上升)
比如 [10,2,2,5,1,7,101,18] 的最长上升子序列是 [2,5,7,101]、[2,5,7,18],长度是4

动态规划 - 状态定义

  • 假设数组是nums,[10,2,2,5,1,7,101,18]
    dp(i)是以nums[i]结尾的最长上升子序列的长度,i ∈ [0,nums.length)
  1. 以nums[0] 10结尾的最长上升子序列是10,所以dp(0) = 1
  2. 以nums[1] 2结尾的最长上升子序列是2,所以dp(1) = 1
  3. 以nums[2] 2结尾的最长上升子序列是2,所以dp(2) = 1
  4. 以nums[3] 5结尾的最长上升子序列是2、5,所以dp(3) = dp(1) + 1 = dp(2) + 1 = 2
  5. 以nums[4] 1结尾的最长上升子序列是1,所以dp(4) = 1
  6. 以nums[5] 7结尾的最长上升子序列是2、5、7,所以dp(5) = dp(3) + 1 = 3
  7. 以nums[6] 101结尾的最长上升子序列是2、5、7、101,所以dp(6) = dp(5) + 1 = 4
  8. 以nums[7] 18结尾的最长上升子序列是2、5、7、18,所以dp(7) = dp(5) + 1 = 4
  • 最长上升子序列的长度是所有dp(i)中最大值max { dp(i) }, i ∈ [0,nums.length)

动态规划 - 状态转义方程

  • 遍历 j ∈ [0,i)
  • 当nums[i] > nums[j]
    nums[i]可以接在nums[j]后面,行程一个比dp(j)更长的上升子序列,长度为dp(j) + 1
    dp(i) = max { dp(i), dp(j) + 1 }
  • 当nums[i] <= nums[j]
    nums[i]不能接在nums[j]后面,跳过此次遍历(continue)
  • 状态的初始值
    dp(0) = 1
    所有的 dp(i) 默认都初始化为1

动态规划 - 实现

int lengthOfLIS(int[] nums) {
    if (nums == null || nums.length == 0) return 0;
    int[] dp = new int[nums.length];
    int max = dp[0] = 1;
    for (int i = 1; i < dp.length; i++) {
        dp[i] = 1;
        for (int j = 0; j < i; j++ ) {
            if (nums[i] <= nums[j]) continue;
            dp[i] = Math.max(dp[i], dp[j] + 1);
        }
        max = Math.max(dp[i], max);
    }
    return max;
}
  • 时间复杂度:O(n),时间复杂度:O(n^2)
发布了163 篇原创文章 · 获赞 18 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/songzhuo1991/article/details/104108981