leetcode673. 最长递增子序列的个数

题目大意

给定一个未排序的整数数组,找到最长递增子序列的个数。

示例 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

解题思路

创建两个数组dp和count,分别记录以j位置结尾的最长递增子序列的长度和个数。对于位置i(i>j),如果nums[i] > nums[j],则表示可以继续构成递增子序列:

  • dp[j] + 1 == dp[i]:表示当前i位置的最长子序列是dp[i],且j位置的最长子序列加上nums[i]后的长度也是dp[i],因此以i位置为结尾的最长子序列的数量可以叠加;
  • dp[j] + 1 > dp[i]:表示以位置j为结尾的最长子序列的长度加上nums[i]后要超过当前i位置的最长子序列,因此dp[i]和count[i]需要被j位置的数据替换掉;
class Solution {
public:
    int findNumberOfLIS(vector<int>& nums) {
    	if (nums.size() < 2)
    		return nums.size();

    	int length = nums.size();

    	vector<int> dp(length, 1);  // 记录长度
    	vector<int> count(length , 1);  // 记录数量

    	int maxLen = 0;

    	for (int i = 0; i < length; ++i){
    		for (int j = 0; j < i; ++j){
    			if (nums[j] < nums[i]){
    				if (dp[j] + 1 > dp[i]){
    					count[i] = count[j];
    					dp[i] = dp[j] + 1;
    				}
    				else if (dp[j] + 1 == dp[i])
    					count[i] += count[j];
    			}
    		}
    		// 每次记录当前最大长度,后续求和需要
    		maxLen = max(maxLen, dp[i]);
    	}

    	int res = 0;
    	for (int i = 0; i < length; ++i)
    		if (dp[i] == maxLen)
    			res += count[i];

    	return res;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_41092190/article/details/106859145