Skip to content

Commit db4156b

Browse files
committed
rivkode longest repeating char replacement
1 parent 977ddb1 commit db4156b

File tree

2 files changed

+119
-1
lines changed

2 files changed

+119
-1
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
1. 문제 이해
3+
4+
입력으로 string s 와 int k 가 있고 s 에 대해 k번 만큼 글자를 바꿀 수 있다.
5+
이때 최대로 연속된 substring의 길이를 찾는 것이다.
6+
즉 k번만큼 바꿀 때 최대의 substring이 될 수 있도록 글자를 바꿔야 한다.
7+
8+
조건: s길이는 최대 10만, k는 최대 s길이
9+
10+
여기서 한가지 포인트는 전체 길이 n 에서 가장 긴 동일 문자 길이 s 를 뺀 값인 n - s 가 k보다 작거나 같다면 이건 항상 전체 길이 만큼에 대해 동일 문자열로 변경할 수 있는것을 의미한다.
11+
왜냐하면 바꿔야할 문자 개수보다 바꿀 수 있는 개수가 더 많기 때문이다.
12+
13+
2. 알고리즘
14+
15+
substring인걸 보니 다이나믹 프로그래밍이 생각나는데 어떻게 적용시켜야할지 고민이다.
16+
작은 문제를 어떻게 정의해야할까 ?
17+
18+
만약 dp가 아니라면?
19+
20+
정답 참고 -> 슬라이딩 윈도우 기법을 사용한다
21+
2개의 포인터를 동일한 인덱스에 놓고 종료 인덱스를 1칸씩 늘려가면서 다른 문자열이 나오는지 체킹한다
22+
23+
3. 예외
24+
25+
26+
4. 구현
27+
28+
GPT 참고
29+
30+
이걸 구현 하는 부분에서 특히 while문을 이해하기 어려웠다.
31+
32+
for문을 통해 end 포인터를 하나씩 증가시킨다
33+
이를 통해 윈도우 크기를 증가시킨다
34+
그리고 counter map에 해당 글자 count를 1 추가하여 넣는다
35+
모든 글자 count들을 돌면서 최대 maxCount를 찾는다
36+
37+
그리고 중요한 조건인 k번을 사용해서 현재 윈도우를 동일한 글자로 만들 수 있는지 찾아낸다.
38+
이때 while문의 (end - start + 1 - maxCount > k) 부분이 핵심이다. 가장 위에서 설명한 대로 현재 윈도우 길이 + 1 - maxCount 가 k보다 크다는 것은 변경해야할 길이가 변경할 수 있는 길이보다 크다는 것이므로 모두 동일한 글자로 만들 수 없다는 것이므로 윈도우 크기를 왼쪽에서 줄여나가야 한다.
39+
40+
이렇게 줄여나가다가 변경해야할 길이 = 변경할 수 있는 길이 가 되면 현재 start ~ end 윈도우에서 가질 수 있는 최대의 동일 글자 길이 조건을 만족시키므로 maxLen를 초기화 시켜준다.
41+
42+
현재 start ~ end 에서 최대 길이를 알아냈으므로 그 다음 end를 증가시키며 이 과정을 반복한다.
43+
44+
45+
GPT 면접식 답변
46+
47+
🎤 ① 문제 핵심 정의부터 말한다
48+
49+
“이 문제의 핵심은
50+
연속된 부분 문자열을 하나 선택했을 때,
51+
최대 k번 문자 교체로 모두 같은 문자로 만들 수 있는지를 판단하는 것입니다.”
52+
53+
🎤 ② 판단 기준을 먼저 제시한다 (중요)
54+
55+
“어떤 부분 문자열의 길이를 n,
56+
그 안에서 가장 많이 등장한 문자의 개수를 s라고 하면,
57+
n - s ≤ k 인 경우에만
58+
이 문자열은 k번 이내의 교체로 하나의 문자로 만들 수 있습니다.”
59+
60+
👉 여기서 면접관은 이미 ‘아, 본질 이해했구나’ 하고 체크함.
61+
62+
🎤 ③ 이 기준을 어떻게 효율적으로 찾는지 설명
63+
64+
“이 조건을 만족하는 가장 긴 n을 찾기 위해
65+
저는 슬라이딩 윈도우를 사용했습니다.”
66+
67+
“오른쪽 포인터를 이동시키며 윈도우를 확장하고,
68+
현재 윈도우 내 문자 빈도를 카운트합니다.”
69+
70+
🎤 ④ 윈도우 유지 조건 설명 (핵심 로직)
71+
72+
“현재 윈도우에서
73+
(윈도우 길이 - 가장 많이 등장한 문자 수)가
74+
k를 초과하면,
75+
해당 구간은 더 이상 유효하지 않으므로
76+
왼쪽 포인터를 이동시켜 윈도우를 줄입니다.”
77+
78+
👉 이 문장이 바로 코드의 while 조건 설명이다.
79+
80+
🎤 ⑤ 정답 갱신 시점 설명
81+
82+
“조건을 만족하는 동안에는
83+
현재 윈도우 길이를 최대값으로 갱신하며
84+
전체 탐색은 한 번만 이루어지므로
85+
시간 복잡도는 O(N)입니다.”
86+
87+
*/
88+
89+
import java.util.*;
90+
91+
class Solution {
92+
public int characterReplacement(String s, int k) {
93+
int maxLen = 0;
94+
Map<Character, Integer> counter = new HashMap<>();
95+
96+
int start = 0;
97+
98+
for (int end = 0; end < s.length(); end++) {
99+
char c = s.charAt(end);
100+
counter.put(c, counter.getOrDefault(c, 0) + 1);
101+
102+
int maxCount = 0;
103+
for (int count : counter.values()) {
104+
maxCount = Math.max(maxCount, count);
105+
}
106+
107+
while (end - start + 1 - maxCount > k) {
108+
char leftChar = s.charAt(start);
109+
counter.put(leftChar, counter.get(leftChar) - 1);
110+
start++;
111+
}
112+
113+
maxLen = Math.max(maxLen, end - start + 1);
114+
}
115+
116+
return maxLen;
117+
}
118+
}

reverse-bits/rivkode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,4 @@ public int reverseBits(int n) {
5151

5252
return decimalValue;
5353
}
54-
}
54+
}

0 commit comments

Comments
 (0)