Longest increasing subsequence in Python

We will learn what a subsequence is and how to calculate the longest increasing subsequence in an array using the n square method and binary search method in Python.


Calculate longest increasing subsequence in Python using N squared method

A famous question was asked about the longest growing subsequence in the Python community and was asked in various interviews. This is a Leetcode problem, the problem is: Given an unsorted array of integers, and find the length of the longest increasing subsequence or subset of the given array.

Subsets are like short arrays of arrays; each array can have multiple subsets. Another thing is that the subarray will be [10,9,2,5,3,7,101,18]some elements in this array, but in a contiguous subsequence fashion.

It could be [2, 3, 5, 7], but it can't be [2,3,101], so there's no need to break the sequence when discussing subarrays. And, subsequently, the order in which the elements appear in the array must be the same, but can be either.

For example, in this case, as we can see, the answer is [2, 3, 7,101]; 5 doesn't exist, but that's okay because it's a subsequence.

If we see the longest increasing subsequence [10,9,2,5,3,7,101,18]from , we'll find [2, 5, 7, 101]; that could also imply an answer, but the answer could also be that [2, 3, 7, 101]this is another subsequence of ours as well. [3, 7, 101]is also a subsequence, but not the longest, so it is not considered.

There may be more than one combination; as we just saw, we only need to return the length.

With this example, we can easily think of a recursive solution starting at index zero and going down all the different paths. Using this array [0,3,1,6,2,2,7], we can take, for example, for 0, we can go to 3, or we can go to 1 or go to 6.

Then, from then on, continue recursively. Looking at the example below, whichever path is the longest will be exponential; it's easy to think that there must be some dynamic programming approach.

So, we have an array where each index has at least one length.

[0,3,1,6,2,2,7]
[1,1,1,1,1,1,1]

We'll start at the first index, 0, which has length 1, but for 3 we can look backwards, and if 3 is greater than 0, then 3 has length 2. If we use 1 again, we'll look at all indices before the current one.

As can be seen from the zero index, 1 is greater than 0, but 1 is not greater than 3, so at this point we calculate 0 and 1, and their length is 2.

[0,3,1,6,2,2,7]
[1,2,2,1,1,1,1]

When considering 6, we look back from the beginning, we know that 6 is greater than [0,1] or [0,3], plus 6, its length is 3, then the length of 2 is also 3, and so on. This is a square method.

[0,3,1,6,2,2,7]
[1,2,2,3,3,...]

Time Complexity and Space Complexity

Let's go into the code and create CalculateSubSequencea class called ; in the lengthOfLIS function we initialize the nums_list variable to the length of nums, the length of the array is only 1 time.

In the nested loop, we will check if the value is greater than the number we are checking. Then, let's take the nums_list of i, we will update the nums_list value while taking the maximum value using nums_list[i].

i comes after iteration from outer loop, for nums_list[j], j comes after iteration from inner loop, then we increment it by 1. Finally, we return the maximum value of nums_list.

class CalculateSubSequence:

    def lengthOfLIS(self, nums: list[int]) -> int:

        nums_list = [1] * len(nums)

        for i in range(len(nums)-1, -1, -1):

            for j in range(i+1, len(nums)):

                if nums[i] < nums[j]:

                    nums_list[i] = max(nums_list[i], nums_list[j] + 1)

        return max(nums_list)

sbs = CalculateSubSequence()
sbs.lengthOfLIS([0,3,1,6,2,2,7])

Here the time complexity is the square of n and the space complexity is o of n.

4

The above solution is sufficient, but another way n log does a binary search on the left side of the temporary array using bisect_left.

from bisect import bisect_left

class CalculateSubSequence:

    def lengthOfLIS(self, nums: list[int]) -> int:
        n= len(nums)
        tmp=[nums[0]]
        for n in nums:
            x = bisect_left(tmp,n)
            if x ==len(tmp):
                tmp.append(n)
            elif tmp[x]>n:
                tmp[x]=n
        return len(tmp)

sbs = CalculateSubSequence()
sbs.lengthOfLIS([0,3,1,6,2,2,7])

output:

4

Guess you like

Origin blog.csdn.net/fengqianlang/article/details/132136501