[Java] 코드트리_흰검칠하기
Categories: Programmers
Tags: CodingTest, 실습
📌 개인적인 공간으로 공부를 기록하고 복습하기 위해 사용하는 블로그입니다.
정확하지 않은 정보가 있을 수 있으니 참고바랍니다 :😸
[틀린 내용은 댓글로 남겨주시면 복받으실거에요]
흰검 칠하기
내가 작성한 코드의 문제점과 수정
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
54
55
56
57
58
59
60
61
import java.util. *;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
// 타일의 색상을 저장할 map
Map<Integer, int[]> map = new HashMap<>();
int loc = 0;
for (int i = 0; i < n; i++) {
int d = sc.nextInt();
String direction = sc.next();
if (direction.equals("L")) { // 왼쪽 흰색
for (int j = loc; j > loc - d; j--) {
int[] counts = map.getOrDefault(j, new int[3]); // counts[0]: 흰색 칠한 횟수, counts[1]: 검은색 칠한 횟수, counts[2]: 마지막 색상
if (counts[2] != 2) {
counts[0]++;
if (counts[0] >= 2 && counts[1] >= 2) {
counts[2] = 2; // 회색으로 변경
} else {
counts[2] = 0; // 마지막 색상을 흰색으로 설정
}
}
map.put(j, counts);
}
loc -= d;
} else { // 오른쪽 검은색
for (int j = loc; j < loc + d; j++) {
int[] counts = map.getOrDefault(j, new int[3]);
if (counts[2] != 2) {
counts[1]++;
if (counts[0] >= 2 && counts[1] >= 2) {
counts[2] = 2;
} else {
counts[2] = 1;
}
}
map.put(j, counts);
}
loc += d;
}
}
int whiteCount = 0, blackCount = 0, grayCount = 0;
for (int key : map.keySet()) {
int[] counts = map.get(key);
if (counts[2] == 2) {
grayCount++;
} else if (counts[2] == 1) {
blackCount++;
} else if (counts[2] == 0) {
whiteCount++;
}
}
System.out.println(whiteCount + " " + blackCount + " " + grayCount);
}
}
문제점 분석
- 카운트 로직 오류
- 코드에서
counts[0]
과counts[1]
은 각 타일이 흰색과 검은색으로 칠해진 횟수인데counts[2] == 2
(타일이 회색인 경우)일 때counts[0]
과counts[1]
의 업데이트가 이루어지지 않는다.
- 코드에서
- 회색 타일로 변경 조건 미충족
- 타일이 회색이 되기 위한 조건은 흰색과 검은색으로 각각 두 번 이상 칠해지는 것이지만
- 코드에서는 타일이 회색이 되면 이후로는
counts[0]
과counts[1]
이 증가하지 않으므로, 이후에 추가로 칠해지는 횟수가 누락되어버림 - 이로 인해 일부 타일이 실제로는 회색이 되어야 하지만 코드에서는 회색으로 처리되지 않는 문제가 발생하게 된다.
수정 방안
타일의 칠해진 횟수(counts[0]
, counts[1]
)는 타일이 회색이 되었더라도 계속해서 업데이트되어야 합니다. 다만, 타일의 색상(counts[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
if (direction.equals("L")) { // 왼쪽으로 이동하며 흰색으로 칠함
for (int j = loc; j > loc - d; j--) {
int[] counts = map.getOrDefault(j, new int[3]);
counts[0]++; // 흰색으로 칠한 횟수 증가
if (counts[0] >= 2 && counts[1] >= 2) {
counts[2] = 2; // 회색으로 변경
} else if (counts[2] != 2) { // 회색이 아닌 경우에만 색상 업데이트
counts[2] = 0; // 마지막 색상을 흰색으로 설정
}
map.put(j, counts);
}
loc -= d;
} else { // 오른쪽으로 이동하며 검은색으로 칠함
for (int j = loc; j < loc + d; j++) {
int[] counts = map.getOrDefault(j, new int[3]);
counts[1]++; // 검은색으로 칠한 횟수 증가
if (counts[0] >= 2 && counts[1] >= 2) {
counts[2] = 2; // 회색으로 변경
} else if (counts[2] != 2) { // 회색이 아닌 경우에만 색상 업데이트
counts[2] = 1; // 마지막 색상을 검은색으로 설정
}
map.put(j, counts);
}
loc += d;
}
counts[0]
과counts[1]
은 타일이 회색이 되었더라도 항상 업데이트된다.- 타일의 색상(
counts[2]
)은 회색(2
)이 아닌 경우에만 업데이트합니다. - 회색으로 변경되는 조건(
counts[0] >= 2 && counts[1] >= 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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import java.util. *;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Map<Integer, int[]> map = new HashMap<>();
int loc = 0;
for (int i = 0; i < n; i++) {
int d = sc.nextInt();
String direction = sc.next();
if (direction.equals("L")) { // 왼쪽 흰색
for (int j = loc; j > loc - d; j--) {
int[] counts = map.getOrDefault(j, new int[3]);
counts[0]++; // 흰색 칠한 횟수 증가
if (counts[0] >= 2 && counts[1] >= 2) {
counts[2] = 2; // 회색으로 변경
} else if (counts[2] != 2) { // 회색이 아닌 경우에만 색상 업데이트
counts[2] = 0; // 흰색으로 설정
}
map.put(j, counts);
}
loc -= d;
} else { // 오른쪽 검은색
for (int j = loc; j < loc + d; j++) {
int[] counts = map.getOrDefault(j, new int[3]);
counts[1]++; // 검은색 칠한 횟수 증가
if (counts[0] >= 2 && counts[1] >= 2) {
counts[2] = 2; // 회색으로 변경
} else if (counts[2] != 2) {
counts[2] = 1; // 검은색으로 설정
}
map.put(j, counts);
}
loc += d;
}
}
int whiteCount = 0, blackCount = 0, grayCount = 0;
for (int[] counts : map.values()) {
if (counts[2] == 2) {
grayCount++;
} else if (counts[2] == 1) {
blackCount++;
} else if (counts[2] == 0) {
whiteCount++;
}
}
System.out.println(whiteCount + " " + blackCount + " " + grayCount);
}
}
풀이 코드
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
import java.util.Scanner;
public class Main {
public static final int MAX_K = 100000;
public static int n;
public static int[] a = new int[2 * MAX_K + 1]; // 타일의 현재 색상을 저장하는 배열
public static int[] cntB = new int[2 * MAX_K + 1]; // 각 타일이 검은색으로 칠해진 횟수
public static int[] cntW = new int[2 * MAX_K + 1]; // 각 타일이 흰색으로 칠해진 횟수
public static int b, w, g; // 검은색, 흰색, 회색 타일의 개수
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
int cur = MAX_K; // 초기 위치 설정 (중앙 위치)
for(int i = 1; i <= n; i++) {
int x = sc.nextInt();
char c = sc.next().charAt(0);
if(c == 'L') { // 왼쪽으로 이동하며 흰색으로 칠함
while(x-- > 0) {
a[cur] = 1; // 현재 타일을 흰색으로 설정
cntW[cur]++; // 흰색으로 칠한 횟수 증가
if(x > 0) cur--; // 다음 타일로 이동
}
}
else { // 오른쪽으로 이동하며 검은색으로 칠함
while(x-- > 0) {
a[cur] = 2; // 현재 타일을 검은색으로 설정
cntB[cur]++; // 검은색으로 칠한 횟수 증가
if(x > 0) cur++; // 다음 타일로 이동
}
}
}
// 모든 타일에 대해 색상 결정
for(int i = 0; i <= 2 * MAX_K; i++) {
if(cntB[i] >= 2 && cntW[i] >= 2) g++; // 흰색과 검은색으로 각각 두 번 이상 칠해진 경우 회색
else if(a[i] == 1) w++; // 흰색 타일
else if(a[i] == 2) b++; // 검은색 타일
}
System.out.print(w + " " + b + " " + g);
}
}
코드 설명
- 타일 배열 (
a[]
)과 카운트 배열 (cntB[]
,cntW[]
)a[]
: 각 타일의 현재 색상을 저장합니다. 0은 칠해지지 않음, 1은 흰색, 2는 검은색cntB[]
,cntW[]
: 각 타일이 검은색 또는 흰색으로 칠해진 횟수를 저장
- 현재 위치 (
cur
)- 중앙 위치인
MAX_K
에서 시작하여 명령에 따라 이동
- 중앙 위치인
- 이동
- 각 명령에 대해
x
만큼 반복하면서 타일의 색상과 칠해진 횟수를 업데이트한다. - 왼쪽(
L
)으로 이동할 때는cur
를 감소시키고, 오른쪽(R
)으로 이동할 때는cur
를 증가시킴
- 각 명령에 대해
- 최종 색상 결정
- 모든 타일을 순회하며
cntB[i]
와cntW[i]
를 확인하여 회색 타일을 결정 - 회색이 아닌 타일은 마지막으로 칠해진 색상인
a[i]
를 참고하여 흰색 또는 검은색 타일의 개수를 증가시킨다.
- 모든 타일을 순회하며
풀이에서는 cur을 배열의 인덱스가 음수가 되지 않도록 100000으로 설정한 것 같은데 처음에 cur을 이해하느라고 애먹었다, 나는 HashMap 사용했는데, 정답 풀이가 깔끔하고 간단해보이긴 한데 배열의 크기가 있어서 메모리상의 이점은 내가 더 좋을 듯 하다.
Leave a comment