1
1
---
2
2
layout : post
3
- title : (Leetcode) 300 - Longest Increasing Subsequence
3
+ title : (Leetcode) 300 - Longest Increasing Subsequence 풀이
4
4
categories : [스터디-알고리즘]
5
- tags : [파이썬, 알고리즘, python, algorithm, Leetcode, DP, bisect, bisect_left, 배열 이진 분할 알고리즘]
5
+ tags :
6
+ [
7
+ 파이썬,
8
+ 알고리즘,
9
+ python,
10
+ algorithm,
11
+ Leetcode,
12
+ DP,
13
+ bisect,
14
+ bisect_left,
15
+ 배열 이진 분할 알고리즘,
16
+ Java,
17
+ 자바,
18
+ Dynamic Programming,
19
+ ]
6
20
date : 2024-02-27 00:30:00 +0900
7
21
image :
8
22
path : /assets/images/2024-02-26-leetcode-300/Page1.png
24
38
class Solution :
25
39
def lengthOfLIS (self , nums : List[int ]) -> int :
26
40
longest = 1
27
-
41
+
28
42
dp = [1 ] + ([float (' -inf' )] * (len (nums) - 1 ))
29
43
30
44
for i, num in enumerate (nums):
@@ -33,7 +47,7 @@ class Solution:
33
47
for j in range (0 , i + 1 ):
34
48
if num > nums[j]:
35
49
dp[i] = max (dp[i], dp[j] + 1 )
36
-
50
+
37
51
if dp[i] == float (' -inf' ):
38
52
dp[i] = 1
39
53
@@ -63,13 +77,13 @@ class Solution:
63
77
lst = []
64
78
for num in nums:
65
79
i = bisect_left(lst, num)
66
-
80
+
67
81
if i == len (lst):
68
82
lst.append(num)
69
-
83
+
70
84
else :
71
85
lst[i] = num
72
-
86
+
73
87
return len (lst)
74
88
```
75
89
@@ -118,3 +132,106 @@ lst [0, 1, 2, 3]
118
132
4 # 최종결과
119
133
```
120
134
135
+ ## Java 로 다시 풀기 (24.07.17)
136
+
137
+ Beats 62.23%
138
+
139
+ ``` java
140
+ class Solution {
141
+ public int lengthOfLIS (int [] nums ) {
142
+ int [] dp = new int [nums. length];
143
+ Arrays . fill(dp, 1 );
144
+
145
+ int max = 1 ;
146
+ for (int i = 1 ; i < nums. length; i++ ) {
147
+ for (int j = 0 ; j < i; j++ ) {
148
+ if (nums[j] < nums[i]) {
149
+ dp[i] = Math . max(dp[j] + 1 , dp[i]);
150
+ }
151
+ }
152
+ max = Math . max(max, dp[i]);
153
+ }
154
+ return max;
155
+ }
156
+ }
157
+ ```
158
+
159
+ ### TC, SC
160
+
161
+ 시간복잡도는 O(n^2), 공간복잡도는 O(n)이다.
162
+
163
+ ## Follow up 문제
164
+
165
+ > Follow up: Can you come up with an algorithm that runs in O(n log(n)) time complexity?
166
+
167
+ 파이썬 에서는 bisect_left 를 쓰면 된다고 하지만 자바에는 존재하지 않는다. 하지만 방법을 찾아보자.
168
+
169
+ ### dp 를 사용하지 않은 풀이 (Beats 82.20%)
170
+
171
+ 우선은 ArrayList를 이용하여 비슷하게 모방해보았다.
172
+
173
+ ``` java
174
+ public int lengthOfLIS(int [] nums) {
175
+ ArrayList<Integer > subsequence = new ArrayList<> ();
176
+ subsequence. add(nums[0 ]);
177
+
178
+ for (int i = 1 ; i < nums. length; i++ ) {
179
+ int current = nums[i];
180
+
181
+ if (current > subsequence. get(subsequence. size() - 1 )) {
182
+ subsequence. addLast(current);
183
+ } else if (current < subsequence. get(0 )) {
184
+ subsequence. set(0 , current);
185
+ } else {
186
+ for (int j = 1 ; j < subsequence. size(); j++ ) {
187
+ if (current > subsequence. get(j - 1 ) && current < subsequence. get(j)) {
188
+ subsequence. set(j, current);
189
+ }
190
+ }
191
+ }
192
+ }
193
+
194
+ return subsequence. size();
195
+ }
196
+ ```
197
+
198
+ #### TC, SC
199
+
200
+ 아직은 여전히 시간복잡도는 O(n^2), 공간복잡도는 O(n)이다.
201
+ 빅오 표기법 상으로는 동일하나 실제 동작 시간은 감소하였다.
202
+
203
+ ### 진짜 binary search를 도입해보기 (Beats 92.57%)
204
+
205
+ 자바 Collections 에서는 binarySearch 메소드를 제공해준다.
206
+ 적용해보면 다음과 같다.
207
+
208
+ ``` java
209
+ public int lengthOfLIS(int [] nums) {
210
+ ArrayList<Integer > subsequence = new ArrayList<> ();
211
+
212
+ for (int current : nums) {
213
+ // Collections.binarySearch : 목록에 포함된 경우 검색 키의 인덱스, 그렇지 않으면 (-(삽입점) - 1) 을 반환함.
214
+ int pos = Collections . binarySearch(subsequence, current);
215
+ if (pos < 0 ) pos = - (pos + 1 );
216
+ if (pos >= subsequence. size()) {
217
+ subsequence. add(current);
218
+ } else {
219
+ subsequence. set(pos, current);
220
+ }
221
+ }
222
+
223
+ return subsequence. size();
224
+ }
225
+ ```
226
+
227
+ #### Collections.binarySearch
228
+
229
+ 해당 메소드의 리턴값은 다음과 같다.
230
+
231
+ > 목록에 포함된 경우 검색 키의 인덱스, 그렇지 않으면 (-(삽입점) - 1).
232
+ > 삽입 지점은 키가 목록에 삽입되는 지점, 즉 키보다 큰 첫 번째 요소의 인덱스 또는 목록의 모든 요소가 지정된 키보다 작은 경우 list.size()로 정의됩니다.
233
+ > 키가 발견되는 경우에만 반환값이 >= 0이 되도록 보장합니다.
234
+
235
+ #### TC, SC
236
+
237
+ 시간복잡도는 ` O(n * logn) ` , 공간복잡도는 ` O(n) ` 이다.
0 commit comments