一、最长递增/减子序列问题
给定数组arr,返回arr的最长递增/减子序列或者子序列长度。
二、分析
1.返回长度
leetcode题解给了dp方法或者贪心二分的方法。
dp方法:
1.确定状态:dp[i]表示的是0到i这一段数组中最长的递减子数组长度。
2.转移方式:从前面寻找可能转移到当前i位置的转移点,比较大小。
以递减序列为例:
package Other.LongestDecreasingSubsequence;
import java.util.Arrays;
public class Solution {
public static void main(String[] args) {
int[] arr={9,4,3,2,5,4,3,2,7,5,56,0,1};
System.out.println(new Solution().LongestDecreasingSubsequence(arr));
}
public int LongestDecreasingSubsequence(int[] arr){
int[] dp=new int[arr.length];
dp[0]=1;
int maxres=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);
}
maxres = Math.max(maxres, dp[i]);
}
System.out.println(Arrays.toString(dp));
return maxres;
}
}
时间复杂度O(n2)
使用贪心加二分的方法可以将复杂度优化至
O(nlogn)
2.返回数组
如果需要返回这个数组,只需要从后往前找就可以了,当然,观察dp数组可知,这个序列并不唯一。
package Other.LongestDecreasingSubsequence;
import java.util.Arrays;
public class Solution {
public static void main(String[] args) {
int[] arr={9,4,3,2,5,4,3,2,7,5,56,1};
System.out.println(Arrays.toString(new Solution().LongestDecreasingSubsequence(arr)));
}
public int[] LongestDecreasingSubsequence(int[] arr){
int[] dp=new int[arr.length];
dp[0]=1;
for (int i = 1; i < arr.length; i++) {
for (int j = 0; j < i; j++) {
if (arr[i]<arr[j])
dp[i]=Math.max(dp[i],dp[j]+1);
}
}
System.out.println(Arrays.toString(dp));
int[] res=new int[dp[arr.length-1]];
int j=res.length-1;
int cur=dp[dp.length-1];
for (int i = arr.length-1; i >= 0; i--) {
if (dp[i]==cur){
res[j]=arr[i];
j--;
cur--;
}
}
return res;
}
}
如果需要返回全部的序列,可以用回溯。
import java.util.Arrays;
public class Solution3 {
public static void main(String[] args) {
int[] arr={9,4,3,2,5,4,3,2,7,5,56,0,1};
new Solution3().LongestDecreasingSubsequence(arr);
}
public void LongestDecreasingSubsequence(int[] arr){
int[] dp=new int[arr.length];
dp[0]=1;
int maxres=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);
}
maxres = Math.max(maxres, dp[i]);
}
System.out.println(Arrays.toString(dp));
back(dp,arr,maxres,new int[maxres],dp.length-1);
}
public void back(int[] dp, int[] arr, int maxres,int[] res,int index){
if (maxres==0){
System.out.println(Arrays.toString(res));
return;
}
if (index<0)
return;
for (int i = index; i >= 0; i--) {
if (dp[i]==maxres){
res[maxres-1]=arr[i];
back(dp,arr,maxres-1,res,i);
res[maxres-1]=0;
}
}
}
}