673. 最长递增子序列的个数(dp)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了673. 最长递增子序列的个数(dp)相关的知识,希望对你有一定的参考价值。

673. 最长递增子序列的个数(dp)

方法1:dp

在用 O ( n 2 ) O(n^2) O(n2) L I S LIS LIS的长度时维护一个 c n t i cnt_i cnti 表示以 i i i结尾的 L I S LIS LIS的个数,然后再维护一个 m a x L e n , a n s maxLen,ans maxLen,ans即可。

时间复杂度: O ( n 2 ) O(n^2) O(n2)

class Solution {
public:
    int findNumberOfLIS(vector<int>& a) {
        int n=(int)a.size();
        vector<int>f(n+1),g(n+1);
        int mx=0,ans=0;
        for(int i=1;i<=n;i++){
            f[i]=g[i]=1;
            for(int j=1;j<i;j++){
                if(a[i-1]>a[j-1]){
                if(f[j]+1>f[i]){
                    f[i]=f[j]+1;
                    g[i]=g[j];
                }
                else if(f[j]+1==f[i]){
                    g[i]+=g[j];
                }
                }
            }
            if(f[i]>mx){
                mx=f[i];
                ans=g[i];
            }
            else if(f[i]==mx) ans+=g[i];
        }
        return ans;
    }
};

方法2:二分+前缀和+贪心。

这个方法比较妙,需要维护两个二维数组。
一个 d ( i , j ) d(i,j) d(i,j) 表示长度为 i − 1 i-1 i1 L I S LIS LIS的第 j j j个末尾元素, d i d_i di中的数是非递增的。

c n t ( i , j ) cnt(i,j) cnt(i,j) 是对应 d ( i , j ) d(i,j) d(i,j) L I S LIS LIS前缀和。

每次我们对于当前数 n u m num num 二分找到 d i d_i di 满足 d [ i ] . b a c k ( ) ≥ n u m d[i].back() \\ge num d[i].back()num 的最小位置 p p p


时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)

class Solution {
    int binarySearch(int n, function<bool(int)> f) {
        int l = 0, r = n;
        while (l < r) {
            int mid = (l + r) / 2;
            if (f(mid)) {
                r = mid;
            } else {
                l = mid + 1;
            }
        }
        return l;
    }

public:
    int findNumberOfLIS(vector<int> &nums) {
        vector<vector<int>> d, cnt;
        for (int v : nums) {
            int i = binarySearch(d.size(), [&](int i) { return d[i].back() >= v; });
            int c = 1;
            if (i > 0) {
                int k = binarySearch(d[i - 1].size(), [&](int k) { return d[i - 1][k] < v; });
                c = cnt[i - 1].back() - cnt[i - 1][k];
            }
            if (i == d.size()) {
                d.push_back({v});
                cnt.push_back({0, c});
            } else {
                d[i].push_back(v);
                cnt[i].push_back(cnt[i].back() + c);
            }
        }
        return cnt.back().back();
    }
};

以上是关于673. 最长递增子序列的个数(dp)的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode 673.最长递增子序列的个数

Leetcode-673 (Number of Longest Increasing Subsequence)最长递增子序列的个数

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

Q673 最长递增子序列的个数

LeetCode 673. 最长递增子序列的个数

动态规划-673. 最长递增子序列的个数