轉載自 : 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] + " ");