二刷 贪心 + 二分 + 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; } }