Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
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
tailsarray of same size as input array, initialize with 0Initialize
size = 0to track the current LIS length-
For each element
xin the input array:Use binary search to find the position where
xshould be placedUpdate
tails[i] = xat the found positionUpdate
sizeif 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.
