Longest Increasing Sequence
Posted 太空工程车
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Longest Increasing Sequence相关的知识,希望对你有一定的参考价值。
1 public class Longest_Increasing_Subsequence { 2 /** 3 * O(N^2) 4 * DP 5 * 思路: 6 * 示例:[1,0,2,4,10,5] 7 * 找出以上数组的LIS的长度 8 * 分析: 9 * 只要求长度,并不要求找出具体的序列 10 * 问题可以拆分为 11 * 1. 对于[1],找出LIS 12 * 2. 对于[1,0],找出LIS 13 * 3. 对于[1,0,2],找出LIS 14 * 4. 对于[1,0,2,4],找出LIS 15 * ... 16 * 最后,对于[1,0,2,4,10,5],找出LIS 17 * 再进一步思考,例如: 18 * 找出[-1,0,1,0,2,4]的LIS,就要找到在4之前符合条件(都比4小且都为升序)的LIS的长度 => [-1,0,1]是满足情况的(最长,都是升序,都比4小) 19 * 那么就要有一个数据结构来记录到某一个index上,LIS的长度。因为每一个index上的LIS长度并不是固定为前一个加1,所以每一个都要记录下来 => 数组dp[] 20 * dp[i]记录的是,在i这个index上,LIS的长度 21 * 比如: 22 * index 0 1 2 3 4 5 23 * dp:[ 1,2,3,1,4,5] //dp数组 24 * ar:[-1,0,1,0,2,4] //原数组 25 * dp[1] = 2表示在1这个index上,LIS的长度是2([-1,0]) 26 * dp[4] = 4表示在4这个index上,LIS的长度是4([-1,0,1,2]) 27 * ---------------------------- 28 * 状态转换方程: 29 * dp[i] = dp[k] + 1; (dp[k] = max(dp[0], dp[1], ... dp[i-1])) // dp[i] = 在i以前最大的LIS长度加上1 30 * 以上方程的成立条件: 31 * nums[k] < nums[i] //保持递增序列的属性 32 */ 33 34 /** 35 * O(N^2) 36 */ 37 public int lengthOfLIS(int[] nums) { 38 int[] dp = new int[nums.length]; 39 dp[0] = 1; 40 for (int i = 1; i < nums.length; i++) { 41 int beforeMaxLen = dp[i]; 42 // 在0 ~ i之间比较LIS的长度 43 for(int j = 0; j < i; j++) { 44 if (nums[j] < nums[i] && dp[j] > beforeMaxLen) { //注意dp[j] > beforeMaxLen,新的长度要大于之前选出来的长度才能更新 45 beforeMaxLen = dp[j]; 46 } 47 } 48 dp[i] = beforeMaxLen + 1; 49 } 50 int max = 0; 51 // 在数组里找出最大的长度即可 52 for (int i = 0; i < nums.length; i++) { 53 if (dp[i] > max){ 54 max = dp[i]; 55 } 56 } 57 return max; 58 } 59 60 /** 61 * O(N*logN) 62 * 思路: 63 * 满足递增序列,就直接加入list中 64 * 如果发现有降序出现,找出在原数组中比它大的第一个数的index,然后在list中替换那个数 65 * 最后返回list的长度 66 * 原理: 67 * 因为只求长度,所以没有必要存储确切的sequence 68 */ 69 public int lengthOfLIS_2(int[] nums) { 70 List<Integer> list = new ArrayList<>(); 71 for(int num : nums) { 72 if(list.isEmpty() || list.get(list.size() - 1) < num) { // 不满足递增序列 73 list.add(num); 74 } else { 75 list.set(findFirstLargeEqual(list, num), num); 76 } 77 } 78 79 return list.size(); 80 } 81 82 private int findFirstLargeEqual(List<Integer> list, int target) 83 { 84 int start = 0; 85 int end = list.size() - 1; 86 while(start < end) { 87 int mid = start + (end - start) / 2; 88 if(list.get(mid) < target) { 89 start = mid + 1; 90 } 91 else { 92 end = mid; 93 } 94 } 95 96 return end; 97 } 98 99 /** 100 * 测试用 101 */ 102 public static void main(String[] args) { 103 Longest_Increasing_Subsequence lis = new Longest_Increasing_Subsequence(); 104 int[] a = {-1,0,1,0,2,4}; 105 System.out.print(lis.lengthOfLIS_2(a)); 106 } 107 }
以上是关于Longest Increasing Sequence的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode Longest Increasing Subsequence
Longest Increasing Subsequence
674. Longest Continuous Increasing Subsequence