###### tags: `Leetcode` `medium` `dynamic programming` `python` `c++` # 673. Number of Longest Increasing Subsequence ## [題目連結:] https://leetcode.com/problems/number-of-longest-increasing-subsequence/ ## 題目: Given an integer array ```nums```, return the number of longest increasing subsequences. **Notice** that the sequence has to be **strictly** increasing. **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 the longest increasing subsequence is 1, and there are 5 increasing subsequences of length 1, so output 5. ``` ## 解題想法: * 此題為給一數組,求最長嚴格遞增的子數組個數 * 使用DP: * 定義兩組: * **dp[i]:以nums[i]為結尾的最長LIS長度** * 初始皆為1,因為自己一個數字長度為1 * **count[i]:以nums[i]為結尾的最長LIS個數** * 初始個數皆為1 * 對於迴圈的進行: * 雙迴圈 * 外圈第一圈: 控制邊界 * for **i** in range(1,n) * 內圈第二圈: 控制範圍 * for **j** in range(**i**) * j在前、i在後~ * 轉移方程式: * 最低門檻: 前面的j需要小於後面的i才可構成嚴格遞增 * if nums[j]<nums[i]: * go 後續Case判斷 * Case1: if dp[j]>=dp[i] * **意義**: 若較小的nums[j]為結尾構成的長度>=較大的nums[i]為結尾構成的長度 * 則**dp[i]=dp[j]+1** (繼承dp[j]的長度並加上1(即加上nums[i])) * 則**count[i]=count[j]** (**數量**直接繼承) * Case2: else if dp[j]+1==dp[i] * **意義**: 若較小的nums[j]為結尾構成的長度(dp[j])比較短,加上nums[i]後,長度==較大的nums[i]為結尾構成的長度(dp[i]) * 則dp數組不用更動 * 則**count[i]+=count[j]** * 數組擴張 * **意義:** 因為count[j]紀錄的是滿足dp[j]長度的個數,藉由加上nums[i]後可以使dp[j]長度+1等於dp[i],所以表示count[j]個數全部都可以累加給count[i],因為長度一樣 * 紀錄最後數量: * 累加最大dp[i]對應的count[i]值即為解 ## Python: ``` python= class Solution(object): def findNumberOfLIS(self, nums): """ :type nums: List[int] :rtype: int """ #dp[i]:以nums[i]為結尾的最長LIS #count[i]:以nums[i]為結尾的最長LIS個數 dp=[1 for _ in range(len(nums))] count=[1 for _ in range(len(nums))] for i in range(1,len(nums)): for j in range(i): #前面j小於後面i才要考慮 if nums[j]<nums[i]: if dp[j]>=dp[i]: dp[i]=dp[j]+1 count[i]=count[j] #原本dp[j]較短 加上 nums[i]後 長度==dp[i],則: #count[i]+=count[j] if dp[j]+1 == dp[i] elif dp[j]+1==dp[i]: count[i]+=count[j] #組數擴張!! res=0 MaxLen=max(dp) for pos,val in enumerate(count): if dp[pos]==MaxLen: res+=val return res nums = [1,3,5,4,7] result=Solution() ans=result.findNumberOfLIS(nums) print(ans) ``` ## C++: * 取數組最大值用max_element,為pointer * [https://shengyu7697.github.io/std-max_element/] ``` cpp= #include<bits/stdc++.h> using namespace std; class Solution { public: int findNumberOfLIS(vector<int>& nums) { int n=nums.size(); vector<int> dp(n, 1), count(n, 1); for (int i=1; i<n; i++){ for (int j=0; j<i; j++){ if (nums[j]<nums[i]){ if (dp[j]>=dp[i]){ dp[i]=dp[j]+1; //length+1 count[i]=count[j]; } else if (dp[j]+1==dp[i]) count[i]+=count[j]; } } } //max_element: get the max value //use pointer get reference int maxLen= *max_element(dp.begin(), dp.end()); int res=0; for (int pos=0; pos<n; pos++){ if (dp[pos]==maxLen) res+=count[pos]; } return res; } }; ```