In this course, we will cover the problem of finding the “Longest Increasing Subsequence” (LIS), which is one of the important concepts in Python coding tests. This problem frequently appears in coding algorithm tests of various IT companies and requires efficient algorithm design and implementation skills. Therefore, it is important to understand and practice it properly.
1. Problem Description
The problem is to find the length of the longest increasing subsequence in a given sequence. A subsequence is formed by selecting some elements from the original sequence while maintaining their order. For example, given the sequence [10, 20, 10, 30, 20, 50], the longest increasing subsequence is [10, 20, 30, 50], which has a length of 4.
2. Problem Approach and Understanding
The longest increasing subsequence problem has the following characteristics:
- The elements of the subsequence must maintain their order in the original sequence.
- We need to find the length of the subsequence, not the subsequence itself.
To solve this problem, two approaches can be used.
- Dynamic Programming approach
- Binary Search approach
2.1 Dynamic Programming Approach
Using dynamic programming, we can maintain the length of the longest increasing subsequence based on each element of the sequence. The time complexity of this approach is O(n^2).
The algorithm using dynamic programming can be described as follows:
- Initialize dp[i] as the length of the increasing subsequence, setting all values to 1.
- For each element i, traverse the previous elements j (j < i), and if arr[j] < arr[i], update dp[i] to dp[j] + 1.
- The final result is the maximum value in the dp array.
2.2 Binary Search Approach
The method using binary search is more efficient, with a time complexity of O(n log n). This approach uses an array called ‘tails’ to store the last elements of the longest increasing subsequences found so far.
The algorithm for the binary search approach can be described as follows:
- Initialize an empty array.
- Traverse the sequence and perform a binary search to find the position to insert the current element in the tails array.
- If the found position is equal to the length of the tails array, add the current element; otherwise, update that position with the current element.
- The final result is the length of the tails array.
3. Algorithm Implementation
3.1 Dynamic Programming Implementation
def longest_increasing_subsequence(arr):
n = len(arr)
dp = [1] * n # Initialization
for i in range(n):
for j in range(i):
if arr[j] < arr[i]:
dp[i] = max(dp[i], dp[j] + 1)
return max(dp)
3.2 Binary Search Implementation
from bisect import bisect_left
def longest_increasing_subsequence(arr):
tails = []
for x in arr:
i = bisect_left(tails, x) # Find index of the first element greater than x
if i == len(tails):
tails.append(x) # Add new element
else:
tails[i] = x # Update element
return len(tails)
4. Examples and Results
Now we will run some examples using the algorithms implemented above.
arr = [10, 20, 10, 30, 20, 50]
print(longest_increasing_subsequence(arr)) # Output: 4
arr = [3, 2, 5, 6, 3, 7, 1]
print(longest_increasing_subsequence(arr)) # Output: 5
arr = [1, 2, 3, 4, 5]
print(longest_increasing_subsequence(arr)) # Output: 5
5. Conclusion
The problem of finding the longest increasing subsequence frequently appears in coding interviews, and can be solved using both dynamic programming and binary search approaches. Through this problem, you can learn both the concept of dynamic programming and the application of binary search, laying the foundation for solving complex algorithm problems.
This concludes the Python coding test course on finding the longest increasing subsequence. I hope this has been helpful in solving algorithm problems. Keep practicing to improve your algorithm skills and prepare for the next coding test!