首页 > 其他 > 详细

[LeetCode] 300. Longest Increasing Subsequence

时间:2020-06-06 10:49:25      阅读:37      评论:0      收藏:0      [点我收藏+]

Given an unsorted array of integers, find the length of longest increasing subsequence.

Example:

Input: [10,9,2,5,3,7,101,18]
Output: 4 
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4. 

Note:

  • There may be more than one LIS combination, it is only necessary for you to return the length.
  • Your algorithm should run in O(n2) complexity.

Follow up: Could you improve it to O(n log n) time complexity?

最长上升子序列。题目就是题意。注意子序列和子串的不同,子序列是可以断开的,只要相对顺序是上升的即可。这个题有两种做法,一是动态规划,一是动态规划基础上的二分。

首先是动态规划。设dp[i]是以nums[i]为结尾的子序列的最大长度。首先初始化的时候,dp数组的每一个元素都是1,因为如果以当前元素为结尾,不看其他元素的话,子序列最大长度就是1。

更新DP数组的方法是用双指针,用一个指针i去遍历input的时候,同时设置另一个指针j扫描j - i的范围,如果在j - i的范围中有数字nums[j] < nums[i],则dp[i] = Math.max(dp[i], dp[j] + 1)

最后要找的结果是DP数组中的最大值。动图帮助理解

时间O(n^2)

空间O(n)

Java实现

 1 class Solution {
 2     public int lengthOfLIS(int[] nums) {
 3         // corner case
 4         if (nums == null || nums.length == 0) {
 5             return 0;
 6         }
 7 
 8         // normal case
 9         int[] dp = new int[nums.length];
10         for (int i = 0; i < dp.length; i++) {
11             dp[i] = 1;
12         }
13         for (int i = 0; i < nums.length; i++) {
14             for (int j = 0; j < i; j++) {
15                 if (nums[i] > nums[j]) {
16                     dp[i] = Math.max(dp[i], dp[j] + 1);
17                 }
18             }
19         }
20         int res = 0;
21         for (int i = 0; i < dp.length; i++) {
22             res = Math.max(res, dp[i]);
23         }
24         return res;
25     }
26 }

 

DP基础上的二分法。创建一个和input等长的input数组,这里的DP数组记录的是实打实的数字,注意最后DP数组中的结果可能并不一定是一个正确的子序列,但是长度是对的。

遍历input,

如果遇到的数字比DP数组里面最大的数字还要大,就加到DP数组的末端;

如果遇到的数字较小,则需要将这个数字通过二分法的方式放到DP数组中他该存在的位置;

时间O(nlogn)

空间O(n)

Java实现

 1 class Solution {
 2     public int lengthOfLIS(int[] nums) {
 3         // corner case
 4         if (nums == null || nums.length == 0) {
 5             return 0;
 6         }
 7 
 8         // normal case
 9         int[] dp = new int[nums.length];
10         dp[0] = nums[0];
11         int len = 0;
12         for (int i = 1; i < nums.length; i++) {
13             int pos = binarySearch(dp, len, nums[i]);
14             if (nums[i] < dp[pos]) {
15                 dp[pos] = nums[i];
16             }
17             if (pos > len) {
18                 len = pos;
19                 dp[len] = nums[i];
20             }
21         }
22         return len + 1;
23     }
24 
25     private int binarySearch(int[] dp, int len, int val) {
26         int left = 0;
27         int right = len;
28         while (left + 1 < right) {
29             int mid = left + (right - left) / 2;
30             if (dp[mid] == val) {
31                 return mid;
32             } else {
33                 if (dp[mid] < val) {
34                     left = mid;
35                 } else {
36                     right = mid;
37                 }
38             }
39         }
40         if (dp[right] < val) {
41             return len + 1;
42         } else if (dp[left] >= val) {
43             return left;
44         } else {
45             return right;
46         }
47     }
48 }

 

LeetCode 题目总结

[LeetCode] 300. Longest Increasing Subsequence

原文:https://www.cnblogs.com/cnoodle/p/13053361.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!