暴力法:
采用递归,如果当前元素大于pre,则序列中包含当前元素,长度加1,如果小于等于pre,考虑下一个元素,结果返回两种情况的最大值。
public class Solution {
public int lengthOfLIS(int[] nums) {
return lengthofLIS(nums, Integer.MIN_VALUE, 0);
}
public int lengthofLIS(int[] nums, int prev, int curpos) {
if (curpos == nums.length) {
return 0;
}
int taken = 0;
if (nums[curpos] > prev) {
taken = 1 + lengthofLIS(nums, nums[curpos], curpos + 1);
}
int nottaken = lengthofLIS(nums, prev, curpos + 1);
return Math.max(taken, nottaken);
}
}
动态规划:令dp[i]为包含nums[i]的数组中最长递增序列的长度,0~i-1中的数都有可能是pre,所以需要遍历0~i-1中的元素,取最大值:
dp[i]=max(dp[j])+1,if nums[i]>nums[j],0<=j<i
结果为max(dp[])。
public class Solution {
public int lengthOfLIS(int[] nums) {
if (nums.length == 0) {
return 0;
}
int[] dp = new int[nums.length];
dp[0] = 1;
int maxans = 1;
for (int i = 1; i < dp.length; i++) {
int maxval = 0;
for (int j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
maxval = Math.max(maxval, dp[j]);
}
}
dp[i] = maxval + 1;
maxans = Math.max(maxans, dp[i]);
}
return maxans;
}
}
此外,可以使用贪心选择 + 二分查找算法
class Solution {
public int lengthOfLIS(int[] nums) {
if(nums.length == 0)
return 0;
int[] lis = new int[nums.length];
int size = 0;
for(int num : nums) {
int i = 0, j = size;
while(i != j) {
int mid = (i + j) / 2;
if(lis[mid] < num) {
i = mid + 1;
}
else {
j = mid;
}
}
lis[i] = num;
if(i == size) {
size++;
}
}
return size;
}
}