Program to find length of longest increasing subsequence in Python

The Longest Increasing Subsequence (LIS) problem asks us to find the length of the longest subsequence where elements are in increasing order. For example, in the array [6, 1, 7, 2, 8, 3, 4, 5], the LIS is [1, 2, 3, 4, 5] with length 5.

We'll solve this using an efficient binary search approach with O(n log n) time complexity.

Algorithm Steps

The algorithm maintains a tails array where tails[i] stores the smallest ending element of all increasing subsequences of length i+1 ?

  • Create a tails array of same size as input array, initialize with 0

  • Initialize size = 0 to track the current LIS length

  • For each element x in the input array:

    • Use binary search to find the position where x should be placed

    • Update tails[i] = x at the found position

    • Update size if we extended the subsequence

Implementation

class Solution:
    def solve(self, nums):
        if not nums:
            return 0
        
        tails = [0] * len(nums)
        size = 0
        
        for x in nums:
            i = 0
            j = size
            
            # Binary search to find the correct position
            while i != j:
                mid = i + (j - i) // 2
                if tails[mid] < x:
                    i = mid + 1
                else:
                    j = mid
            
            # Place x at position i
            tails[i] = x
            size = max(i + 1, size)
        
        return size

# Test the solution
ob = Solution()
nums = [6, 1, 7, 2, 8, 3, 4, 5]
print("Input:", nums)
print("Length of LIS:", ob.solve(nums))
Input: [6, 1, 7, 2, 8, 3, 4, 5]
Length of LIS: 5

How It Works

Let's trace through the algorithm with input [6, 1, 7, 2, 8, 3, 4, 5] ?

def solve_with_trace(nums):
    tails = [0] * len(nums)
    size = 0
    
    print(f"Processing array: {nums}")
    print("Step by step:")
    
    for x in nums:
        i = 0
        j = size
        
        # Binary search
        while i != j:
            mid = i + (j - i) // 2
            if tails[mid] < x:
                i = mid + 1
            else:
                j = mid
        
        tails[i] = x
        size = max(i + 1, size)
        
        print(f"Element {x}: position={i}, tails={tails[:size]}, size={size}")
    
    return size

nums = [6, 1, 7, 2, 8, 3, 4, 5]
result = solve_with_trace(nums)
print(f"\nFinal LIS length: {result}")
Processing array: [6, 1, 7, 2, 8, 3, 4, 5]
Step by step:
Element 6: position=0, tails=[6], size=1
Element 1: position=0, tails=[1], size=1
Element 7: position=1, tails=[1, 7], size=2
Element 2: position=1, tails=[1, 2], size=2
Element 8: position=2, tails=[1, 2, 8], size=3
Element 3: position=2, tails=[1, 2, 3], size=3
Element 4: position=3, tails=[1, 2, 3, 4], size=4
Element 5: position=4, tails=[1, 2, 3, 4, 5], size=5

Final LIS length: 5

Testing with Different Examples

def test_lis():
    solution = Solution()
    
    test_cases = [
        [10, 9, 2, 5, 3, 7, 101, 18],
        [0, 1, 0, 3, 2, 3],
        [7, 7, 7, 7, 7, 7, 7],
        [1, 3, 6, 7, 9, 4, 10, 5, 6]
    ]
    
    for i, nums in enumerate(test_cases, 1):
        result = solution.solve(nums)
        print(f"Test {i}: {nums}")
        print(f"LIS length: {result}")
        print()

test_lis()
Test 1: [10, 9, 2, 5, 3, 7, 101, 18]
LIS length: 4

Test 2: [0, 1, 0, 3, 2, 3]
LIS length: 4

Test 3: [7, 7, 7, 7, 7, 7, 7]
LIS length: 1

Test 4: [1, 3, 6, 7, 9, 4, 10, 5, 6]
LIS length: 5

Time and Space Complexity

Aspect Complexity Explanation
Time O(n log n) Binary search for each element
Space O(n) Additional tails array

Conclusion

This binary search approach efficiently finds the LIS length in O(n log n) time. The tails array maintains the smallest ending elements for subsequences of each length, allowing optimal placement of new elements.

Updated on: 2026-03-25T11:21:16+05:30

631 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements