给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
示例 1:
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。
示例 2:
输入:nums = [0,1,0,3,2,3]
输出:4
示例 3:
输入:nums = [7,7,7,7,7,7,7]
输出:1
看了半天,题都看不懂,我也是无语,后来发现,题上有坑,只是告诉你子序列,没有告诉你这个就是它的最长递增子序列,审题呀!
static int count = 0;
static public int lengthOfLIS(int[] nums) {
dfs(nums, new ArrayList<>(), 0, 0);
return count;
}
public static void dfs(int[] nums, List<Integer> list, int index, int sum) {
count = Math.max(sum, count);
if (nums.length - index + list.size() <= count) {// 剩下的不够了,不需要往下走
return;
}
for (int i = index; i < nums.length; i++) {
if (list.size() == 0 || list.get(list.size() - 1) < nums[i]) {// 满足递增
list.add(nums[i]);
dfs(nums, list, i + 1, sum + 1);
list.remove(list.size() - 1);
} else {// 不满足递增,则继续往下寻找能满足递增的值
dfs(nums, list, i + 1, sum);
}
}
}
方法二:动态规划
我们分析
int[] nums1 = { 5, 7, -24, 12, 13, 2, 3, 12, 5, 6, 35 };
5:前面没有数,为1个长度
7:左有比7小的5,Math.max(dp[0]+1,dp[1]),取2
-24:左有5、7>-24,不满足题意,设长度为1
12:左边的都<12,取他们中间dp最大的+1
13:左边的都<13,取他们中间dp最大的+1
2:前面只有-24<2,取它的dp值+1
3:前面-24,-2<3,取中间dp最大的+1
12:前面5、7、-24、2、3<12,但是根据题意,最多-24、2、3、12或者5、7、12连成子序列,选取最大的dp+1
5:-24,2,3<5,取dp最大的+1
6:5、-24、2、3、5<6,取dp最大的+1
35:左边都比35小,取左边dp最大的+1
// 动态规划
static public int lengthOfLIS2(int[] nums) {
if (nums.length == 0) {
return 0;
}
int[] dp = new int[nums.length];
dp[0] = 1;
int max = dp[0];
for (int i = 1; i < nums.length; i++) {
dp[i] = 1;
for (int j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
max = Math.max(max, dp[i]);
}
return max;
}
}
总结:动态规划我现在做起来真的太难了。