Skip to content

Commit 57817d1

Browse files
committed
Added improved solution to question 300.
1 parent b9b7e91 commit 57817d1

File tree

1 file changed

+63
-7
lines changed

1 file changed

+63
-7
lines changed

leetcode/medium/300_longest_increasing_subsequence.md

+63-7
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,22 @@
11
# 300. Longest Increasing Subsequence
22

3-
## Iterative Solution
4-
- Runtime: O(N^2)
3+
## Dynamic Programming Solution
4+
- Run-time: O(N^2)
55
- Space: O(N)
66
- N = Number of elements in array
77

88
If we were to start from the left to the right, we would have seen the longest subsequence on the left side as we are going to the right.
9-
Inorder for us to know what those longest subsequences were, we will need a way to store that, hello dynamic programming.
9+
In-order for us to know what those longest subsequences were, we will need a way to store that, hello dynamic programming.
1010

1111
For each element, we would need look at the numbers on the left that are less than the current element.
1212
Now that we know which numbers those are, we can then look at their corresponding longest subsequence in the dynamic programming array.
13-
From this list, get the longest subsequence.
14-
15-
We are basically building the longest increasing subsequence from the bottom up.
13+
Therefore, dp[i] = max(for previous dp[j] elements which num[i] < num[j]).
1614

1715
**Example:**
1816
```
1917
Input(I): [10,9,2,5,3,7,101,18]
2018
21-
DP:
19+
DP:
2220
10 [1, 1, 1, 1, 1, 1, 1, 1]
2321
9 [1, 1, 1, 1, 1, 1, 1, 1] -> DP[1] = 1 + max([]) (I[1] not > I[0])
2422
2 [1, 1, 1, 1, 1, 1, 1, 1] -> DP[2] = 1 + max([]) (I[2] not > I[0],I[1])
@@ -37,3 +35,61 @@ class Solution:
3735
dp[index] = 1 + max([dp[j] for j in range(index) if nums[index] > nums[j]], default=0)
3836
return max(dp, default=0)
3937
```
38+
39+
## Dynamic Programming with Binary Search Solution
40+
- Run-time: O(Nlog(N))
41+
- Space: O(N)
42+
- N = Number of elements in array
43+
44+
Slightly modifying the previous approach.
45+
We can use a dynamic programming 1d array of 0s but instead store the subsequence themselves instead of what the previous longest subsequence were.
46+
The 1d array can be thought of as keeping a sorted array within itself, there will be a subset of indexes that would represent the longest subsequence.
47+
48+
With this sorted array, we can then binary search it to find where a given n should be placed.
49+
We want to find a number that is greater than or equal to n, then replace that number in the array.
50+
If a number isn't found, we can increase the range of indexes in the sorted array by 1 and add the new n at the end.
51+
By increasing the sorted array by 1, it shows that there is a longer subsequence.
52+
This won't exactly tell us the 'actual' subsequence because of the replacement and ordering but works since the question only cares about what is the longest subsequence.
53+
54+
```
55+
Input: [1,3,6,7,9,4,10,5,6]
56+
57+
[0, 0, 0, 0, 0, 0, 0, 0, 0]
58+
[1, 0, 0, 0, 0, 0, 0, 0, 0]
59+
[1, 3, 0, 0, 0, 0, 0, 0, 0]
60+
[1, 3, 6, 0, 0, 0, 0, 0, 0]
61+
[1, 3, 6, 7, 0, 0, 0, 0, 0]
62+
[1, 3, 6, 7, 9, 0, 0, 0, 0]
63+
[1, 3, 4, 7, 9, 0, 0, 0, 0]
64+
[1, 3, 4, 7, 9, 10, 0, 0, 0]
65+
[1, 3, 4, 5, 9, 10, 0, 0, 0]
66+
[1, 3, 4, 5, 6, 10, 0, 0, 0]
67+
```
68+
69+
```
70+
class Solution(object):
71+
def lengthOfLIS(self, nums):
72+
73+
def binary_search_insertion_idx(n):
74+
left, right = 0, end_idx
75+
insert_idx = -1
76+
while left <= right:
77+
mid_idx = left + ((right - left) // 2)
78+
if memo[mid_idx] >= n:
79+
insert_idx = mid_idx
80+
right = mid_idx - 1 # go left
81+
else: # go right
82+
left = mid_idx + 1
83+
return insert_idx
84+
85+
memo = [0] * len(nums)
86+
end_idx = -1
87+
for n in nums:
88+
idx = binary_search_insertion_idx(n)
89+
if idx == -1: # no number found greater than n
90+
end_idx += 1
91+
memo[end_idx] = n
92+
else: # found a number that is greater than n
93+
memo[idx] = n
94+
return end_idx + 1
95+
```

0 commit comments

Comments
 (0)