leetcode012-Number of Longest Increasing Subsequence

来源:互联网 发布:mac 鼠标指针大小 编辑:程序博客网 时间:2024/06/05 09:07

Given an unsorted array of integers, find the number of longest increasing subsequence.

Example 1:

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

Example 2:

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

Note: Length of the given array will be not exceed 2000 and the answer is guaranteed to be fit in 32-bit signed int.


这道题明显是leetcode300. Longest Increasing Subsequence的变体。LIS是在最一个序列里找到最长的递增子序列的长度。

example: [84, -48, -33, -34, -52, 72, 75, -12, 72, -45]

  • scan from left to right,  the longest that ends at 84: [84] (1)
  •  ... ends at -48: [-48] (1)
  •  ... ends at -33: [-48, -33] (2)
  •  ... ends at -34: [-48, -34] (2)
  •  ... ends at -52: [-52] (1)
  •  ... ends at  72: [-48, -33, 72] or [-48, -34, 72] (3)
  •  ... ends at  75: [-48, -33, 72, 75] or [-48, -34, 72, 75] (4)
  •  ... ends at -12: [-48, -33, -12] or [-48, -34, 12] (3)
  •  ... ends at  72: [-48, -33, -12, 72] or [-48, -34, 12, 72] (4)
  •  ... ends at -45: [-48, -45], [-52,-45] (2)
通过观察我们可以发现,当我们寻找第i个位置的最长子序列长度时是通过遍历位置i左边所有数值小于nums[i]的位置,找出当中对应长度最大的一个,然后取那个数加1(相当于nums[i]续在它所能续(它必须比它想续的序列的最后一个位置的数大)的序列中的最长一条),我们用dp[i]记录位置当序列结束在位置i时,该序列的最大长度。

所有的元素都能自成一条序列,因此用1初始化dp数组。
dp[i] = max{dp[j]+1 | nums[i] > nums[j] }
 
解题思路:LIS的变体要求输出最长子序列的个数,因此我为每个位置增加一个变量dp[i].second来记录状态转移的方程中max{dp[j]+1}有多少个j同时符合跳转要求。
                  从当前位置往回扫描的过程中,一旦发现有比当前发现的最长“可续”序列更长的序列时,更新max值,更新from值。from值记录的是要多少条符合max值的子序列。如果发现是相同长度序列(即max值相等), 则from要在原基础上加上当前位置所能代表的几条子序列。
                  如果在往回扫描的过程中,并没有可续的子序列,则from值为0,dp[i].second不变保持为1。如果有可续的,则dp[i].second更新为from值所记录的条数。
 

    int findNumberOfLIS(vector<int>& nums) {        // dp[i].first: the length of the longest increasing subsequence ends at string[i]        vector<pair<int, int>> dp(nums.size(),make_pair(1, 1));        int ans = 1;        for (int i = 1; i < nums.size(); i++) {            int max = 0;  // 用于更新左边符合要求的最长子序列的长度            int from = 0;            for (int j = i-1; j >= 0; j--) {                if (nums[i] > nums[j]) {                    if (dp[j].first > max) {                        max = dp[j].first;                        from = dp[j].second;                    } else if (dp[j].first == max) {                        from += dp[j].second;                    }                }            }            if (max != 0) {                dp[i].first += max;                dp[i].second = from;            }            // 最长子序列的长度更新            if (dp[i].first > ans) ans = dp[i].first;        }        if (ans == 1) return dp.size();        int sum = 0;        for (int i = 0; i < dp.size(); i++) {            if (dp[i].first == ans) {                sum += dp[i].second;            }        }        return sum;    }



原创粉丝点击