LeetCode 673. Number of Longest Increasing Subsequence (Java版; Meidum)

welcome to my blog

LeetCode 673. Number of Longest Increasing Subsequence (Java版; Meidum)

题目描述
Given an unsorted array of integers, find the number of longest increasing subsequence.

Example 1:
Input: [1,3,5,4,7]
Output: 2
Explanation: The two longest increasing subsequence are [1, 3, 4, 7] and [1, 3, 5, 7].
Example 2:
Input: [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.
Note: Length of the given array will be not exceed 2000 and the answer is guaranteed to be fit in 32-bit signed int.
第二次做; 这道题和LC300本质是相同的; 核心: 1) 出现递增时考虑更新dp[i]和count[i] 2)两个一维DP
class Solution {
    public int findNumberOfLIS(int[] nums) {
        //input check
        //
        int n = nums.length;
        //dp[i]表示以nums[i]结尾时的LIS长度
        int[] dp = new int[n];
        //count[i]表示以nums[i]结尾的LIS的个数
        int[] count = new int[n];
        for(int i=0; i<n; i++){
            dp[i] = 1;
            count[i] = 1;
        }
        int max=0;
        int res=0;
        for(int i=0; i<n; i++){
            for(int j=0; j<i; j++){
                if(nums[i] > nums[j]){
                    if(1+dp[j] > dp[i]){
                        dp[i] = 1 + dp[j];
                        count[i] = count[j];
                    }
                    else if(1+dp[j]==dp[i]){
                        count[i] += count[j];
                    }
                }
            }
            //update
            if(dp[i] > max){
                max = dp[i];
                res = count[i];
            }
            else if(dp[i]==max){
                res += count[i];
            };
        }
        return res;
    }
}
第一次做; 直接看了优秀题解; 两个一维动态规划, 核心:1) len[i]表示以nums[i]结尾的字符串的最长递增子序列的长度, cnt[i]表示以nums[i]结尾的字符串的最长递增子序列的个数; 2) 在nums[i] > nums[j]的情况下, 比较len[i] 和 len[j]+1; 3) substring往往使用单层循环, subsequence问题往往使用双层循环
/*
动态规划
两个一维动态规划
*/
class Solution {
    public int findNumberOfLIS(int[] nums) {
        if(nums==null || nums.length==0)
            return 0;
        int n = nums.length;
        //len[i]表示以nums[i]结尾的字符串的最长子序列长度
        int[] len = new int[n];
        //cnt[i]表示以nums[i]结尾的字符串的最长子序列的个数
        int[] cnt = new int[n];
        //记录出现过的最大长度
        int max=0;
        //记录最终的结果
        int res = 0;
        //DP主体
        for(int i=0; i<n; i++){
            //自身构成的最长子序列
            len[i] = 1;
            cnt[i] = 1;
            //对于每个i, 只考虑[0,i-1]范围的情况
            for(int j=0; j<i; j++){
                //如果出现递增, 该如何更新数组?
                if(nums[i] > nums[j]){
                    //len[i] 与 len[j] + 1 之间的比较
                    if(len[i] == len[j] + 1 ){
                        cnt[i] += cnt[j];
                    }
                    else if(len[i] < len[j] + 1){
                        len[i] = len[j] + 1;
                        cnt[i] = cnt[j];
                    }
                }
            }
            //
            if(len[i] > max){
                max = len[i];
                res = cnt[i];
            }
            else if(len[i] == max){
                res += cnt[i];
            }
        }
        return res;
    }
}
leetcode优秀题解 分析中还指出了substring问题一般用单层循环,因为当前元素只与相邻的元素有关系; subsequence问题一般用双层循环,因为当前元素可能与任何其他的元素都有关系
for those guys who are not quite familiar with this type of problem, please also check No.549. Binary Tree Longest Consecutive Sequence II to 
have a better understanding..
for each element in the array or on in the tree, they all carry three fields :
1) the maximum increasing / decreasing length ends at the current element,
2) its own value ,
3) the total number of maximum length,
and each time when we visit a element, we will use its 2) to update 1) and 3), the only difference is for array we use iteration while for tree
we use recursion......
Also, for substring problem, we usually use only one for loop because for each index, we only care about the relationship between its two neighbors,
while for subsequence problem, we use two for loops , because for each index, any other indexes can do something...
public int findNumberOfLIS(int[] nums) {
        int n = nums.length, res = 0, max_len = 0;
        int[] len =  new int[n], cnt = new int[n];
        for(int i = 0; i<n; i++){
            len[i] = cnt[i] = 1;
            for(int j = 0; j <i ; j++){
                if(nums[i] > nums[j]){
                    if(len[i] == len[j] + 1)cnt[i] += cnt[j];
                    if(len[i] < len[j] + 1){
                        len[i] = len[j] + 1;
                        cnt[i] = cnt[j];
                    }
                }
            }
            if(max_len == len[i])res += cnt[i];
            if(max_len < len[i]){
                max_len = len[i];
                res = cnt[i];
            }
        }
        return res;
    }
力扣官方题解 使用了线段树

你可能感兴趣的:(字符串,动态规划,算法,leetcode,数据结构)