LeetCode -- Longest Increasing Subsequence(LIS)
Question:
Given an unsorted array of integers, find the length of longest increasing subsequence.
For example,
Given [10, 9, 2, 5, 3, 7, 101, 18]
,
The longest increasing subsequence is [2, 3, 7, 101]
, therefore the length is 4
. Note that 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?
Analysis:
给出一个由正整数构成的数组,找出里面最长的子序列。(序列,不要求每个数字都是连续的)
例如:给出数组{10, 9, 2, 5, 3, 7, 101, 18},最长的子序列为{2, 3, 7, 101},因此长度为4. 注意可能有不止一个LIS序列,这里仅仅要求你返回他们的长度。
要求算法的时间复杂度为O(n2).
Follow up: 你可以将时间复杂度提升到O(nlogn)嘛?
思路:由于前面做过判断是否存在长度为3的递增子序列,按照相似的思路,乍一眼看到这个问题感觉比较简单,可以很容易的解决,结果后面越分析越复杂。只管来说应该按照DP的思想解决,但是前面做过N多关于DP的题目了,仍然对这类题目还是不开窍。。好郁闷。。因此在网上参考了九章算术的答案。具体思路是,用一个额外的数组现将到该位置时的子序列长度设为1,然后从第一个元素开始往当前元素循环(简单来说就是加一层循环看前面有几个元素比当前元素小),然后更新result最为最终的返回结果。
(通过上面及以前的分析可知,一般动态规划的题目都可以牺牲一点空间复杂度来达到目的,如果暂时想不出DP的状态转化公式且题目没有明显的要求空间复杂度时可考虑先用额外的数组等来存储每步的转态,至少保证能够解答出题目)。
Answer:
public class Solution { public int lengthOfLIS(int[] nums) { if(nums == null) return 0; int[] num = new int[nums.length]; int result = 0; for(int i=0; i<nums.length; i++) { num[i] = 1; for(int j=0; j<i; j++) { if(nums[j] < nums[i]) { num[i] = num[i] > num[j] + 1 ? num[i] : num[j] +1; } } if(num[i] > result) result = num[i]; } return result; } }