Summary of related topics for increasing subsequences

table of Contents

1. The longest continuous increasing sequence

2. The longest ascending subsequence

3. The number of the longest increasing subsequence

4. Increasing subsequence

5. The longest continuous sequence


Here are some topics related to increasing subsequences. Some topics will have optimal solutions, but the main focus here is on the practice of dynamic programming , so only dynamic programming or some general methods are written.

Before introducing these topics, first distinguish between what is a subsequence and what is a substring

Subsequence: The subsequence is not continuous, such as the sequence  [4, 6, 5] is  [1, 2, 4, 3, 7, 6, 5] a subsequence

Substring: The substring is continuous

1. The  longest continuous increasing sequence

Input: [1,3,5,4,7]
Output: 3
Explanation: The longest continuous increasing sequence is [1,3,5], and the length is 3.
Although [1,3,5,7] is also an ascending subsequence, it is not continuous because 5 and 7 are separated by 4 in the original array. 

This question is about increasing sequence, but the requirement is continuous, so it is actually seeking increasing substring

class Solution:
    def findLengthOfLCIS(self, nums: List[int]) -> int:
        if not nums:
            return 0
        if len(nums) == 1:
            return 1
        dp = [1]*len(nums) #代表连续递增序列的长度
        for i in range(1,len(nums)):
            if nums[i]>nums[i-1]: #如果后一个元素大于前一个元素,那长度+1
                dp[i] = dp[i-1]+1
        return max(dp) # 找出最大的那个数就是长度,不能是dp[-1],dp[-1]代表的是以最后一个元素结尾是最长连续递增序列,但是最后一个并不一定是最大的数。

2. The  longest ascending subsequence

Use dynamic programming to do it, define the dp array to represent the length of the subsequence, dp[i] represents any element before the i-th element as the starting point, and the length of the ascending subsequence to the end of the i-th element , initialized to 1 , Which means that each element can at least become a subsequence individually, and the length is 1 at this time.

After traversing to each element nums[i], traverse the elements nums[j] in [0-i] from the beginning. If nums[i]>nums[j], then nums[i] can be accessed To the back of the nums[j] element, that is, dp[i] = dp[j] + 1 

So the recursive equation is dp[i] = max(dp[i],dp[j]+1) 0\leq j<i, in the end, we still find max(dp) instead of dp[-1]

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        if not nums:
            return 0
        dp=[1]*len(nums)
        for i in range(len(nums)):
            for j in range(i):
                if nums[i]>nums[j]:
                    dp[i] = max(dp[i],dp[j]+1)
        return max(dp)

If the inner loop of this question traverses from 0 every time, there are actually many repeated traversals, so the inner loop can use the dichotomy to find the first number greater than num[i], and then replace it with num[i], not much to say, the code is as follows:

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        res = []
        for num in nums:
            if not res or num>res[-1]:
                res.append(num)
            else:
                l=0
                r=len(res)-1
                while l<r:
                    mid = (l+r)//2
                    if res[mid]<num:
                        l = mid+1
                    else:
                        r = mid
                res[l]=num
        return len(res)

3. The number of the longest increasing subsequence

This question is very similar to the one above, except that there is an additional count of the number of the longest increasing subsequence

class Solution:
    def findNumberOfLIS(self, nums: List[int]) -> int:
        if not nums:
            return 0
        dp = [1]*len(nums)
        count = [1]*len(nums)
        temp = 1
        res = 0
        for i in range(1,len(nums)):
            for j in range(i):
                if nums[i]>nums[j]:
                    if dp[j]+1>dp[i]:
                        dp[i] = dp[j]+1
                        count[i] = count[j]
                    elif dp[i] == dp[j]+1:
                        count[i]+=count[j]
            # temp = max(temp,dp[i])
        temp = max(dp)
        for i in range(len(nums)):
            if dp[i] == temp:
                res += count[i]
        return res

When dp[j]+1> dp [i], it means that the new length is found for the first time, which is dp[j]+1. At this time, count[i] = count[j], indicating  nums[i] the longest ending The combination of increasing subsequences is equal to the  nums[j] current combination

When dp[j]+1 = dp [i], it means that the increasing sequence of this length has been found once, then  count[i]+=count[j],the number of existing combinations plus count [j] is the total combination Number

The last traversal is to find the longest length, and its corresponding count is the result

You can also use a tree array for this question. Currently, the ability is limited, so I don’t know how to use a tree array. Skip

4. Increasing subsequence

This problem is no longer using dynamic programming, but depth-first search, similar to backtracking. If you use the general backtracking solution, it takes too much time. The code is as follows

class Solution:
    def __init__(self):
        self.res = []
    def findSubsequences(self, nums: List[int]) -> List[List[int]]:
        
        def dfs(temp,start,nums):
            if len(temp)>=2 and temp not in self.res:
                self.res.append(temp[:])
            for i in range(start,len(nums)):
                if not temp or nums[i]>=temp[-1]:
                    temp.append(nums[i])
                    dfs(temp,i+1,nums)
                    temp.pop()
        temp = []
        dfs(temp,0,nums)
        return self.res

It can be seen that it takes more than 6,000 milliseconds to use a collection to pruning is still taking too long, you can use a dictionary to pruning.

class Solution:
    def findSubsequences(self, nums: List[int]) -> List[List[int]]:
        res = []
        def dfs(start, tmp):
            dic = {}
            if len(tmp) > 1:
                res.append(tmp)
            for i in range(start, len(nums)):
                if dic.get(nums[i], 0):
                    continue

                if len(tmp) == 0 or nums[i] >= tmp[-1]:
                    dic[nums[i]] = 1
                    dfs(i + 1, tmp + [nums[i]])


        dfs(0, [])
        return res

The time consuming dropped all of a sudden.

5. The longest continuous sequence

Leave it empty first, learn and check the collection and then improve it

Guess you like

Origin blog.csdn.net/Matrix_cc/article/details/106903435