zoukankan      html  css  js  c++  java
  • [LeetCode] 673. Number of Longest Increasing Subsequence

    Given an integer array nums, return the number of longest increasing subsequences. 

    Example 1:

    Input: nums = [1,3,5,4,7]
    Output: 2
    Explanation: The two longest increasing subsequences are [1, 3, 4, 7] and [1, 3, 5, 7].
    

    Example 2:

    Input: nums = [2,2,2,2,2]
    Output: 5
    Explanation: The length of longest continuous increasing subsequence is 1, and there are 5 subsequences' length is 1, so output 5.
    

    Constraints:

    • 1 <= nums.length <= 2000
    • -106 <= nums[i] <= 106

    最长递增子序列的个数。题意不难理解,思路还是动态规划。

    做这个题之前建议先熟悉一下300题的动态规划的做法。对于这道题,我们需要两个额外数组来记录一些信息,长度都和input数组一样,一个是DP数组,表示以 nums[i] 结尾的最长递增子数组的长度;一个是counter数组,表示以 nums[i] 结尾的最长递增子序列的数量。其中DP数组的初始化和更新方法和300题类似。对于在0 - i 之间的某个下标 j 而言,如果nums[j] < nums[i] 那么dp[i] 肯定可以被更新成dp[j] + 1;但是 counter[i] 怎么更新呢?注意因为counter[i] 的定义是以 nums[i] 为结尾的最长子序列的个数,因为nums[i] > nums[j] 所以如果把nums[i] 加到一个以 nums[j] 为结尾的递增子序列上,这个新的子序列一定也能维持递增,所以counter[i] = counter[j]。

    但是如果dp[j] + 1 == dp[i],意思是如果以 nums[j] 结尾的子序列的长度 + 1 = 以 nums[i] 为结尾的子序列的长度的话,counter[i] 的数量要 += counter[j]。举个例子,比如现在有一个以5结尾的子数组,他的长度是x,现在又发现一个以4为结尾的子数组,他的长度是x - 1的话,这样后者就能插入前者,使得以5为结尾的子数组的个数 = x + x - 1。最后记录一个变量max,记录全局范围内最大的DP值。

    再次遍历DP数组,如果dp[i] = max,则把 counter[i] 累加到结果里面。因为 dp[i] 是最长的递增子序列的长度,所以 counter[i] 是这个最长长度子序列的个数。

    时间O(n^2)

    空间O(n)

    Java实现

     1 class Solution {
     2     public int findNumberOfLIS(int[] nums) {
     3         // corner case
     4         if (nums == null || nums.length == 0) {
     5             return 0;
     6         }
     7 
     8         // normal case
     9         int n = nums.length;
    10         // 以nums[i]结尾的最长递增子序列的长度
    11         int[] dp = new int[n];
    12         // 以nums[i]结尾的最长递增子序列的数量
    13         int[] counter = new int[n];
    14         Arrays.fill(dp, 1);
    15         Arrays.fill(counter, 1);
    16         int max = 0;
    17         for (int i = 0; i < n; i++) {
    18             for (int j = 0; j < i; j++) {
    19                 if (nums[j] < nums[i]) {
    20                     if (dp[j] + 1 > dp[i]) {
    21                         dp[i] = Math.max(dp[i], dp[j] + 1);
    22                         counter[i] = counter[j];
    23                     } else if (dp[j] + 1 == dp[i]) {
    24                         counter[i] += counter[j];
    25                     }
    26                 }
    27             }
    28             max = Math.max(max, dp[i]);
    29         }
    30         int res = 0;
    31         for (int i = 0; i < n; i++) {
    32             if (dp[i] == max) {
    33                 res += counter[i];
    34             }
    35         }
    36         return res;
    37     }
    38 }

    LeetCode 题目总结

  • 相关阅读:
    基于Form组件实现的增删改和基于ModelForm实现的增删改
    Git和Github的基本操作
    如果获取的数据不是直接可以展示的结构---三种操作方式
    可迭代对象和迭代器生成器
    django之整体复习
    权限管理之大致流程
    kindedit编辑器和xxs攻击防护(BeautifulSoup)的简单使用
    博客系统之评论树与评论楼相关操作
    中介模型以及优化查询以及CBV模式
    angularjs中ajax请求时传递参数的方法
  • 原文地址:https://www.cnblogs.com/cnoodle/p/13912612.html
Copyright © 2011-2022 走看看