Skip to content

Commit b63b035

Browse files
add post '(Leetcode) 76 - Minimum Window Substring 풀이'
1 parent ee3537e commit b63b035

File tree

3 files changed

+207
-0
lines changed

3 files changed

+207
-0
lines changed

_posts/2024-07-29-leetcode-76.md

+207
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
---
2+
layout: post
3+
title: (Leetcode) 76 - Minimum Window Substring 풀이
4+
categories: [스터디-알고리즘]
5+
tags:
6+
[
7+
자바,
8+
java,
9+
리트코드,
10+
Leetcode,
11+
알고리즘,
12+
Hash Table,
13+
String,
14+
Sliding Window,
15+
window,
16+
]
17+
date: 2024-07-29 17:00:00 +0900
18+
toc: true
19+
---
20+
21+
기회가 되어 [달레님의 스터디](https://github.com/DaleStudy/leetcode-study)에 참여하여 시간이 될 때마다 한문제씩 풀어보고 있다.
22+
23+
[https://neetcode.io/practice](https://neetcode.io/practice)
24+
25+
---
26+
27+
[https://leetcode.com/problems/minimum-window-substring/description/](https://leetcode.com/problems/minimum-window-substring/description/)
28+
29+
## 내가 작성한 풀이
30+
31+
문제 자체는 엄청 어렵지는 않았다. 다만 어떻게 최적화 해볼 수 있을까 고민하는데 많은 시간이 필요했다.
32+
33+
컨셉은 기본적으로 window 를 사용했다는 것으로 동일하다.
34+
35+
필요한 문자들이 무엇인지 확인하기 위해 counter 변수를 사용한다.
36+
우선 start를 0으로 고정시킨 상태로 오른쪽으로 1칸씩 window를 늘리며 필요한 모든 문자가 포함되었는지 확인한다.
37+
minLength와 minLengthStart 값을 찾게되면 거기서부터는 start도 1씩 늘리면서 minLength를 찾아나간다.
38+
39+
## 버전 1
40+
41+
```java
42+
class Solution {
43+
public String minWindow(String s, String t) {
44+
if (s.length() < t.length()) {
45+
return "";
46+
}
47+
48+
Map<Character, Integer> counter = new HashMap<>();
49+
50+
for (int i = 0; i < t.length(); i++) {
51+
counter.merge(t.charAt(i), 1, Integer::sum);
52+
}
53+
54+
int start = 0;
55+
56+
int minLength = 0;
57+
int minStart = 0;
58+
59+
for (int i = 0; i < s.length(); i++) {
60+
// update counter
61+
char currentChar = s.charAt(i);
62+
63+
Integer count = counter.get(currentChar);
64+
if (count != null) {
65+
counter.merge(currentChar, -1, Integer::sum);
66+
} else {
67+
continue;
68+
}
69+
70+
// check all count is 0 -> update min;
71+
while (validate(counter)) {
72+
int currentLength = i + 1 - start;
73+
if (minLength > currentLength || minLength == 0) {
74+
minStart = start;
75+
minLength = currentLength;
76+
}
77+
78+
// try to move start to start + 1
79+
// increase count if front char exist in counter
80+
count = counter.get(s.charAt(start));
81+
if (count != null) {
82+
if (count == 0) {
83+
break;
84+
}
85+
86+
counter.put(s.charAt(start), count + 1);
87+
}
88+
start++;
89+
}
90+
}
91+
92+
return s.substring(minStart, minStart + minLength);
93+
}
94+
95+
private boolean validate(Map<Character, Integer> counter) {
96+
for (int count : counter.values()) {
97+
if (count > 0) {
98+
return false;
99+
}
100+
}
101+
return true;
102+
}
103+
}
104+
```
105+
106+
![submit_result_1](/assets/images/2024-07-29-leetcode-76/submit_result_1.png)
107+
108+
### TC, SC
109+
110+
문제에 다음과 같이 제시되어 있다.
111+
112+
```java
113+
m == s.length
114+
n == t.length
115+
```
116+
117+
시간 복잡도는 `O(n * m)`, 공간 복잡도는 `O(n)` 이다.
118+
119+
## 버전 2 :성능 우선 버전
120+
121+
사실 이 버전은 실제 어플리케이션에서는 쓰지 않을지도 모르겠다. 이해하는데 좀 더 시간이 걸릴 것 같기 때문이다.
122+
123+
```java
124+
class Solution {
125+
public String minWindow(String s, String t) {
126+
if (s.length() < t.length()) {
127+
return "";
128+
}
129+
130+
Integer[] counter = new Integer[123]; // 적당히 넉넉한 배열 할당
131+
132+
char[] mustContainCharArray = t.toCharArray();
133+
for (char mustContainChar : mustContainCharArray) {
134+
int count = counter[mustContainChar] == null ? 0 : counter[mustContainChar];
135+
count = count + 1;
136+
counter[mustContainChar] = count;
137+
}
138+
139+
int start = 0;
140+
141+
int minLength = 0;
142+
int minLengthFrom = 0;
143+
144+
for (int i = 0; i < s.length(); i++) {
145+
char currentChar = s.charAt(i);
146+
147+
Integer count = counter[currentChar];
148+
if (count != null) {
149+
count = count - 1;
150+
counter[currentChar] = count;
151+
}
152+
153+
// check all count is 0 -> update min;
154+
while (validate(counter)) {
155+
int currentLength = i + 1 - start;
156+
if (minLength > currentLength || minLength == 0) {
157+
minLengthFrom = start;
158+
minLength = currentLength;
159+
}
160+
161+
// try to move start to start + 1
162+
// increase count if front char exist in counter
163+
count = counter[s.charAt(start)];
164+
if (count != null) {
165+
if (count == 0) {
166+
break;
167+
}
168+
169+
counter[s.charAt(start)] = count + 1;
170+
}
171+
start++;
172+
}
173+
}
174+
175+
return s.substring(minLengthFrom, minLengthFrom + minLength);
176+
}
177+
178+
private boolean validate(Integer[] counter) {
179+
for (int i = 65; i < counter.length; i++) { // 65부터 알파벳이 시작하기 때문에 그 이전 값은 의미없다.
180+
Integer count = counter[i];
181+
if (count == null) {
182+
continue;
183+
}
184+
185+
if (count > 0) {
186+
return false;
187+
}
188+
}
189+
return true;
190+
}
191+
}
192+
```
193+
194+
![submit_result_2](/assets/images/2024-07-29-leetcode-76/submit_result_2.png)
195+
196+
시간이 개선되었다.
197+
198+
### TC, SC
199+
200+
문제에 다음과 같이 제시되어 있다.
201+
202+
```java
203+
m == s.length
204+
n == t.length
205+
```
206+
207+
시간 복잡도는 `O(n*m)`, 공간 복잡도는 `O(1)` 이다. 표현상으로는 시간복잡도는 동일하나 실제 실행 시간은 줄어들었고, 공간복잡도는 줄어들게 되었다.
Loading
Loading

0 commit comments

Comments
 (0)