알고리즘/인프런(자바(Java) 알고리즘 문제풀이 입문
4-3 매출액의 종류(Hash, Sliding Window)
person456
2024. 1. 6. 16:11
문제 링크 : https://cote.inflearn.com/contest/10/problem/04-03
** 맨 처음 제출한 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
import java.util.*;
import java.util.stream.Stream;
import java.io.*;
class Main{
static int n,m,k;
static StringTokenizer st;
static StringBuilder sb;
public static void main(String[] args)throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
st = new StringTokenizer(br.readLine(), " ");
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine(), " ");
int[] arr = new int[n];
for(int i=0; i<n; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
int start=0;
int end=m;
sb = new StringBuilder();
while(end<=n) {
Map<Integer, Integer>map = new HashMap<>();
int cnt=0;
for(int i=start; i<end; i++) {
int tmp = arr[i];
if(map.containsKey(tmp)) {
continue;
}else {
cnt++;
map.put(tmp, 1);
}
}
start++;
end++;
sb.append(cnt+" ");
}
System.out.println(sb.toString());
br.close();
bw.close();
}
}
|
cs |
- 시간초과 발생
- 투포인터 느낌으로 start와 end 포인터를 통해 윈도우의 크기만큼 반복을 진행하고자 하였으나, 윈도우의 크기가 N의 최대 크기인 10만까지 가능했었음.
- 10만의 제곱으로 인해 제한시간 초과가 발생. 개인적인 생각으로 문제의 답은 맞지 않았을까 함.
- 맵을 while 안에 생성하는 것으로 계속 초기화를 하면 정확성 있는 답을 얻을 것이라 생각했음.
** 변경 이후 코드 (1차)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
import java.util.*;
import java.util.stream.Stream;
import java.io.*;
class Solution{
static int n,m,k;
static StringTokenizer st;
static StringBuilder sb;
public static void main(String[] args)throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
st = new StringTokenizer(br.readLine(), " ");
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine(), " ");
int[] arr = new int[n];
for(int i=0; i<n; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
Map<Integer, Integer>map = new HashMap<>();
sb = new StringBuilder();
int start=0;
for(int i=0; i<n; i++) {
int key = arr[i];
if(map.containsKey(key)) {
int tmp = map.get(key);
tmp++;
map.put(key, tmp);
}else {
map.put(key, 1);
}
if(i==m-1) {
sb.append(map.size()+" ");
continue;
}
if(i>=m) {
int now = arr[start++];
int value = map.get(now);
if(value>1) {
value--;
map.put(now, value);
}else {
map.remove(now);
}
sb.append(map.size()+" ");
}
}
System.out.println(sb.toString());
br.close();
bw.close();
}
}
|
cs |
- 기존 코드는 투포인터의 최대 장점 O(n) 시간복잡도의 장점을 살리지 못했음. 최악 O(n²)
- 슬라이딩 윈도우를 진행하며, Map에 해당 key가 존재한다면 Value를 1씩 증가하는 방식을 사용
- 반복의 범위를 통해 변수 i(포인터 중 Right)가 윈도우의 크기를 넘어선다면, Left포인터 증가를 실시
- 이 과정중, Value가 1초과면 값을 1낮추고, 1보다 같거나 작다면 Map에서 삭제를 진행
** 변경 이후 코드(2차)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
import java.util.*;
import java.util.stream.Stream;
import java.io.*;
class Solution{
static int n,m,k;
static StringTokenizer st;
static StringBuilder sb;
public static void main(String[] args)throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
st = new StringTokenizer(br.readLine(), " ");
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine(), " ");
int[] arr = new int[n];
for(int i=0; i<n; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
Map<Integer, Integer>map = new HashMap<>();
sb = new StringBuilder();
int start=0;
for(int i=0; i<m; i++) {
map.put(arr[i], map.getOrDefault(arr[i], 0)+1);
}
sb.append(map.size()+" ");
for(int i=m; i<n; i++) {
map.put(arr[i], map.getOrDefault(arr[i], 0)+1);
map.put(arr[start], map.get(arr[start])-1);
if(map.get(arr[start])==0)map.remove(arr[start]);
start++;
sb.append(map.size()+" ");
}
System.out.println(sb.toString());
br.close();
bw.close();
}
}
|
cs |
- map.getOrDefault라는 함수를 통해, Key가 존재하면 그에 해당하는 Value를 가져오고 아니면 0을 반환하는 기능이 있다는 것을 새롭게 배움.
- 이를 통해 기존의 if-else를 통한 코드의 길이보다 훨씬 간결해지며 보기 좋아졌음.