LIS算法
- 定义dp[i]为:以ai为末尾的最长上升子序列的长度
- dp[i]包括:
- 只包括自己,也就是它前面的元素全部都比它大,例子{7,9,6,10,7,1,3},则dp[6] == 1 第六个是1
- 为了保证上升子序列尽可能长,那么就有dp[i]尽可能大,但是再保证dp[i]尽可能大的基础上,还得保证序列上升。则ai > aj && i > j ?dp[j] +1 : 1 , 当第i个数前面有一个第j个数满足条件,找最大dp[j] ,说明ai元素可以接在aj元素的后面,且最长。
O( )
class Solution { public int lengthOfLIS(int[] nums) { int len = nums.length; int flag [] = new int [len]; int ans = 0; for(int i = 0 ; i < len ; i++){ flag[i] = 1; for(int j = 0 ; j < i ;j++){ if(nums[i]>nums[j]){ flag[i] = Math.max(flag[i],flag[j]+1); } } ans = Math.max(ans,flag[i]); System.out.println(ans+" "+flag[i]); } return ans; } }
LIS的nlogn优化【贪心】
- 例子{4,2,3,1,2,3,5}这个序列
- 开一个数组arr[10]
- 第一个数是4,先加进去 ->{4}
- 第二个数是2,比4小,2替换4 ->{2}
- 第三个数是3,比2大,加入 ->{2,3}
- 第四个数是1,比3 、 2还小
O(nlogn)
public int lengthOfLIS(int[] nums) { // O(n) 二分+dp int[] top = new int[nums.length]; int piles = 0; for (int i = 0; i < nums.length; i++) { int poker = nums[i]; int left = 0, right = piles; while (left < right) { int mid = (left + right) / 2; if (top[mid] > poker) { right = mid; } else if (top[mid] < poker) { left = mid + 1; } else { right = mid; } } if (left == piles) piles++; top[left] = poker; } return piles; }