二刷 贪心 + 二分 + dp 保存状态
tail 保存 长度为 i的子序列的 最小的结尾的值(贪心+二分)
dp 保存 位置为i的 最长子序列长度
import java.util.*;
public class Solution {
/**
* retrun the longest increasing subsequence
* @param arr int整型一维数组 the array
* @return int整型一维数组
*/
public int[] LIS (int[] arr) {
int[] tail = new int[arr.length];
int[] dp = new int[arr.length];
tail[0] = arr[0];
int end = 0;
for (int i = 1; i < arr.length; i++) {
if (arr[i] > tail[end]) {
tail[++end] = arr[i];
dp[i] = end;
}
else {
int l = 0;
int r = end - 1;
while (l <= r) {
int mid = (l + r) / 2;
if (arr[i] > tail[mid] && arr[i] <= tail[mid + 1]) {
l = mid+1;
break;
} else if (arr[i] > tail[mid]) {
l = mid + 1;
} else {
r = mid - 1;
}
}
tail[l] = arr[i];
dp[i] = l;
}
}
// 寻找最小字典序
int [] res = new int[end+1];
int i = arr.length-1;
for(;i>=0 && end >=0; i--){
if(dp[i]==end){
res[end] = arr[i];
end--;
}
}
return res;
}
}动态规划
从最后一个开始选就可以 保证是最小字典序
import java.util.*;
public class Solution {
/**
* retrun the longest increasing subsequence
* @param arr int整型一维数组 the array
* @return int整型一维数组
*/
public int[] LIS (int[] arr) {
if( arr.length<2){
return arr;
}
int[] dp = new int[arr.length];
dp[0] = 1;
int maxans = 1;
for (int i = 1; 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);
}
}
maxans = Math.max(maxans, dp[i]);
}
// 寻找最小字典序
int [] res = new int[maxans];
int i = arr.length-1;
for(;i>=0 && maxans >0; i--){
if(dp[i]==maxans){
res[maxans-1] = arr[i];
maxans--;
}
}
return res;
}
}



京公网安备 11010502036488号