写点什么

【LeetCode】最长递增子序列的个数 Java 题解

作者:Albert
  • 2022-11-03
    北京
  • 本文字数:1214 字

    阅读完需:约 4 分钟

题目描述

给定一个未排序的整数数组 nums , 返回最长递增子序列的个数 。


注意 这个数列必须是 严格 递增的。


示例 1:
输入: [1,3,5,4,7]输出: 2解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, 3, 5, 7]。
示例 2:
输入: [2,2,2,2,2]输出: 5解释: 最长递增子序列的长度是1,并且存在5个子序列的长度为1,因此输出5。
来源:力扣(LeetCode)链接:https://leetcode.cn/problems/number-of-longest-increasing-subsequence著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
复制代码

思路分析

  • 今天的算法题目是数组题目,题目要求找出其中 最长严格递增子序列的个数。我们把这个问题分解成两个子问题,一个子问题是求最长严格递增子序列。第二个是求求最长严格递增子序列的个数。

  • 求最长严格递增子序列是经典问题,有多种解法,首先可以使用基础动态规划方法解决,思路的核心是以 nums[i] 为结尾的最长上升子序列。定义 DP 数组,初始化 DP[i] = 1, 然后采用 for 双重循环, 定义变量 j 且 j < i, 在 [j, i] 区间,动态更新递增的最大值。基础的 DP 的时间复杂度是 O(n * n), 空间复杂度是 O(n)。

  • 求出了最长严格递增子序列,我们还需要求最长严格递增子序列的个数。我们在这里定义一个 cnt 计数器,当 dp[j] + 1 == dp[i], cnt[i] += cnt[j]来累加相同长度出现的次数。当 dp[j] + 1 > dp[i]时,重新计数。具体实现代码如下,供参考。

通过代码

class Solution {    public int findNumberOfLIS(int[] nums) {        int n = nums.length;        int ans = 0;        int maxLength = 0;        if (n == 0) {            return ans;        }
int[] dp = new int[n]; int[] cnt = new int[n]; dp[0] = 1; cnt[0] = 1; maxLength = Math.max(dp[0], maxLength); ans = Math.max(1, ans);
for (int i = 1; i < n; i++) { dp[i] = 1; cnt[i] = 1; for (int j = 0; j < i; j++) { if (nums[i] > nums[j]) { if (dp[j] + 1 > dp[i]) { dp[i] = dp[j] + 1; cnt[i] = cnt[j]; } else if (dp[j] + 1 == dp[i]) { cnt[i] += cnt[j]; } } } if (dp[i] > maxLength) { maxLength = dp[i]; ans = cnt[i]; } else if (dp[i] == maxLength) { ans += cnt[i]; } } return ans; }}
复制代码

总结

  • 上述算法的时间复杂度是 O(n * n), 空间复杂度是 O(n)

  • 这个题目非常经典,我们采用分治的思想,将这个题目拆分成两个子问题,逐个击破,解决问题。多练习几遍,体会更深。

  • 坚持算法每日一题,加油!

发布于: 刚刚阅读数: 3
用户头像

Albert

关注

还未添加个人签名 2019-09-29 加入

LeetCode,略懂后端的RD

评论

发布
暂无评论
【LeetCode】最长递增子序列的个数Java题解_算法_Albert_InfoQ写作社区