转载自 : https://leetcode.com/problems/longest-increasing-subsequence/discuss/74880/JAVA-Easy-Version-To-Understand!!!!!!!! 照着自己的理解翻译了一下
方法一:(O(nlgn))
1. 用一个长度为n的数组 increasingSequence 存储递增序列 , 一个dp数组存放当前最长长度,同时用一个变量len存储该数组长度 , 最开始将第一个元素存入数组 ;
2. 从第二个元素开始遍历 , 如果该元素大于increasingSequence 数组的最后一个元素 , 则将该元素存入increasingSequence 数组 , 同时更新dp数组
3. 如果该元素小于等于increasingSequence 数组的最后一个元素 , 则在increasingSequence数组中寻找一个位置保存该元素, 但是长度不变 , 保持increasingSequence数组始终保存着一个递增序列 (到最后arr数组中不一定保存着最长递增序列的原始元素 , 但是长度是一样的 , dp数组则是保存每个元素作为最长子序列的最后一个元素时的长度)
代码如下 :
public class solution{
static int len = 0;
public static int findPositionToReplace(int[] a, int low, int high, int x){
int mid;
while (low <= high){
mid = low + (high - low) / 2;
if (a[mid] == x)
return mid;
else if (a[mid] > x)
high = mid - 1;
else
low = mid + 1;
}
return low;
}
public static int[] lengthOfLIS(int[] nums) {
if (nums == null || nums.length == 0)
return null;
int n = nums.length;
int[] dp = new int[n];
int[] increasingSequence = new int[n];
increasingSequence[len++] = nums[0];
dp[0] = 1;
for (int i = 1; i < n; i++){
if(nums[i] > increasingSequence[len - 1]){
increasingSequence[len++] = nums[i];
dp[i] = len;
}
else{
int position = findPositionToReplace(increasingSequence, 0, len - 1, nums[i]);
increasingSequence[position] = nums[i];
dp[i] = position + 1;
}
}
return dp;
}
public static void main(String [] args)
{
int [] arr = {9,8,7,1,4,5,6};
int [] dp = lengthOfLIS(arr);
int max_index = 0;
System.out.println("len = " + len);
for(int i = len - 1; i >= 0; i--)
{
if(dp[i] == len)
{
max_index = i;
break;
}
}
for(int i = max_index; i >= 0; i--)
if(arr[i] < arr[max_index] && dp[i] == dp[max_index] - 1)
{
System.out.println(arr[i]);
max_index = i;
}
}
}
方法二:(O(n*2))
1. 用一个dp数组存放着每一个元素作为输出序列的最后一个值的最大长度
int [] dp = new int[arr.length];
for(int i = 0; i < arr.length; i++){
dp[i] = 1;
for(int j = 0; j < i; j++)
if(arr[i] > arr[j])
dp[i] = Math.max(dp[i],dp[j]+1);
}
2. 遍历dp数组,得到最大长度和该下标
int index = 0;
int len = 0;
for(int i = 0; i < arr.length; i++)
if(dp[i] > len){
index = i;
len = dp[i];
}
3. 获得该序列每一个元素(该序列的每一个元素小于后一个元素且在dp数组中必须和后一个元素的最大长度相差1)
int [] res = new int [len];
res[--len] = arr[index];
for(int i = index; i >= 0; i--)
if(arr[i] < index && dp[i] == dp[index] - 1){
res[--len] = arr[i]; //将该元素存入res数组
index = i; //更新下标
}
4. 输出该数组
for(int i = 0; i < res.length; i++)
System.out.println(res[i] + " ");