力扣300最长上升子序列
给定一个无序的整数数组,找到其中最长上升子序列的长度。
- 解法一动态规划 时间复杂度O(n)
还是那句话,子序列问题几乎都可以用动态规划解决。
dp[i]的含义为数组在前i+1位中的最长上升子序列长度。dp[i]等于在num[j]小于num[i]条件下的最大值加1 代码如下。
class Solution { public int lengthOfLIS(int[] nums) { if (nums.length == 0) { return 0; } int res = 1; int[] dp = new int[nums.length + 1]; for (int i = 0; i < nums.length; i++) { int max = 0; for (int j = 0; j < i; j++) { if (nums[j] < nums[i]) { max = Math.max(dp[j + 1], max); } } dp[i + 1] = max + 1; res =Math.max(res,dp[i+1]); } return res; } }
- 解法二
构建有序辅助数组,利用二分法来代替方法一种的第二层for循环。时间复杂度O(NlogN)
辅助数组help[]含义:数组中的索引值index,代表着最长子串的index位的值。通过对index二分,找到第一个小于num[i]的索引。若help[index+1]为0 ,则help[bound] = nums[i]。否则为nums[i]和index[i+1]中的最小值。
代码如下
1 package Leetcode; 2 3 public class lengthOfLIS1 { 4 public int lengthOfLIS(int[] nums) { 5 if(nums.length<2){return nums.length;} 6 int[] help = new int[nums.length]; 7 help[0] = nums[0]; 8 int bound = 0; 9 for (int i = 1; i < nums.length; i++) { 10 int right = bound; 11 int left = 0; 12 int index = getIndex(help,right,nums[i]); 13 if(index+1>bound){ 14 bound++; 15 help[bound] = nums[i]; 16 }else{ 17 help[index+1] = Math.min(help[index+1],nums[i]); 18 } 19 } 20 return bound+1; 21 } 22 23 private int getIndex(int[] help, int right, int num) { 24 int left = 0; 25 int mid; 26 while (left<=right){ 27 mid = left+(right-left)/2; 28 if(help[mid]>=num){ 29 right = mid-1; 30 }else{ 31 left = mid+1; 32 } 33 } 34 return right; 35 } 36 37 }

浙公网安备 33010602011771号