题目
Given an unsorted array of integers, find the length of longest increasing subsequence.
Example:
Input: [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.
解法
注意:子序列,不要求连续
解法一:傻叉解法,比较好想
思路是:设置一个数组dp,dp[i]表示,以i位置结尾的最长递增子序列
转移方程是:dp[i] = max(dp[j] + 1) (array[j] < array[i] && j < i)
public static int maxIncreaseSubarray2(int[] array) {
// 傻逼解法
if(array == null || array.length == 0) return 0;
int ans = 1;
int len = array.length;
int[] memo = new int[len];
Arrays.fill(memo, 1);
// 以每个位置结尾的最长递增子序列
for(int i = 1; i < len; i++) {
for(int j = 0; j < i; j++) {
if(array[i] > array[j])
memo[i] = Math.max(memo[i], memo[j] + 1);
}
ans = Math.max(ans, memo[i]);
}
return ans;
}
解法二:排序后,找最长公共子序列
不解释;虽然我也想不到
public static int maxIncreaseSubarray(int[] array) {
// 解法二:排序后,找最长公共子序列
int[] copy = Arrays.copyOf(array, array.length);
Arrays.sort(copy);
// 复习一下求最长公共子序列的方法= =
int len = copy.length;
int[][] dp = new int[len][len];
dp[0][0] = copy[0] == array[0] ? 1 : 0;
for(int i = 1; i < len; i++) {
dp[0][i] = copy[0] == array[i] ? 1 : dp[0][i - 1];
}
for(int i = 1; i < len; i++) {
dp[i][0] = copy[i] == array[0] ? 1 : dp[i - 1][0];
}
for(int i = 1; i < len; i++) {
for(int j = 1; j < len; j++) {
if(copy[i] == array[j]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
}else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[len - 1][len - 1];
}
解法三:
参考:https://blog.csdn.net/love20165104027/article/details/79618367
思路:设置一个数组tail, (假设从1开始)tail[i]表示最长递增子序列长度为i时,最小的结尾元素。
再解释:就是,在数组array中,找递增子序列,可能找到长度为2的若干递增子序列;那么tail[2] 就表示,这些子序列中,第二个元素(最后一个元素)最小的那个值。
遍历数组,
- 如果当前位置j,的元素cur,大于tail数组的最后一个元素tail[k](也就是说,存在k+1长度的递增子序列),将该元素加入tail尾部;
- 如果当前元素cur,小于tail数组的最后一个元素tail[k](也就是说,不能直接接在后面),则在tail数组中找刚好大于cur的元素位置为l,值为ele,即ele大于cur,而ele前面的元素小于cur。表示:长度为l的递增子序列,其最小值可以为cur。用cur替换l位置的值ele。
遍历到最后,tail数组的长度,就是最长递增子序列的长度。
Note: tail数组并不是最长递增子序列!
就……迷迷糊糊,似懂非懂?
public static int maxIncreaseSubarray(int[] array) {
if(array == null || array.length <= 0) return 0;
int len = array.length;
int[] tail = new int[len];
int size = 0;
tail[0] = array[0];
for(int i = 1; i < len; i++) {
if(array[i] > tail[size]) {
tail[++size] = array[i];
}else {
// 这里可以用二分查找,优化时间
int j;
for(j = size - 1; j >= 0; j--) {
if(array[i] > tail[j]) {
break;
}
}
tail[j + 1] = array[i];
}
}
return size + 1;
}