문제분석:
이 문제는 Level3정도 줘도 대는문제다. 로직설계도 어려운데다가, 구현난이도도 어렵다.
격자마다 빛을쏘는 통로가 4개 존재한다.
격자마다 그림을 보고, 빛을받는통로까지 8개를 구현할 필요가없다. 이 문제의 빛은 범위를 넘어간다면,
반대편쪽으로 빛이 돌아오므로, 빛을 쏘는 통로만 확인한다면, 빛을 받는통로는 확인할필요가 없다.
목표는 빛의 사이클이 나오는 모든경우를 반환하는것이다.
빛의 사이클이 되는건 어느 한 통로로 빛을쏜뒤, 이미 방문한 통로를 만나면 하나의 사이클이다.
빛의 사이클을 찾으러면 모든 통로를 한번쯤은 쏴봐야한다. 즉 3차반복을돌려야한다.[모든행,모든 격자, 4개의 통로]
로직이 돌아가는 형태다. 자세한 구현은 문제 풀이에서 해설하겠다.
문제풀이:
격자마다, 4개의 통로(위,아래,우,왼) 과 타입(S,R,L)이 있다. 격자의 형태를 설정할,
Lense클래스를 설정하고, boolean[4]의 통로와(이걸로 방문체크를함), String형 타입명을 선언한다.
격자를 생성할 Lense를 만들었다면, Lense들을 저장할 board 리스트를 전역변수로 저장한다.
빛의 사이클을 저장할 리스트 ,cycle도 저장한다.
3차 반복을 진행하는데, k(방향)에 따라 렌즈를 이동한다.
렌즈를 이동하기전에, 다음렌즈의 타입에 따라 k(방향)을 회전한다.
k(방향)을 회전할 reflect메소드를 구현했다.
reflect메소드는 다음격자가 S,R,L에따라 방향을 바꾸는 역할을한다.
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
import java.util.*;
class Solution {
List<Lense[]> board = new ArrayList<Lense[]>();
List<Integer> cycle =new ArrayList<>();
public int[] solution(String[] grid){
int cnt=0;
//렌즈배치
for(int i=0;i<grid.length;i++){
String[] temp =grid[i].split("");
board.add(new Lense[temp.length]);
for(int j=0;j<temp.length;j++){
board.get(i)[j]=new Lense(temp[j]);
}
}
//3차반복[모든행,모든격자,모든통로]
for(int i=0;i<grid.length;i++){
for(int j=0;j<board.get(i).length;j++){
for(int k=0;k<4;k++){
while(true){
//방문했으면 탈출, 방문 안했으면 진행
if(board.get(i)[j].dir[k]==true){
if(cnt==0){
}
else{
cycle.add(cnt);
cnt=0;
}
break;
}
//이 아래부턴 방문X일때:
//방문했으니, true설정 board.get(i)[j].dir[k]=true;
//방향(k)에따라 렌즈이동 if(k==0){
i++; if(i==board.size()){i=0;}
}
else if(k==1){
j++; if(j==board.get(i).length){j=0;}
}
else if(k==2){
i--; if(i<0){i=board.size()-1;}
}
else if(k==3){
j--; if(j<0){j=board.get(i).length-1;}
}
//이동할 렌즈(다음렌즈)에 따라 방향(k)회전
k=reflect(i,j,k);
//사이클 세주기 cnt++;
}
}
}
}
//모든 사이클을 구했다면, 정렬하고 출력
Collections.sort(cycle);
int[] answer = new int[cycle.size()];
for(int i=0;i<cycle.size();i++){
answer[i]=cycle.get(i);
}
return answer;
}
//렌즈의 타입의따른 방향회전 public int reflect(int i,int j ,int k){
int dir=k;
if(board.get(i)[j].type.equals("S")){
}
else if(board.get(i)[j].type.equals("L")){
dir++; if(dir>3){dir=0;}
}
else if(board.get(i)[j].type.equals("R")){
dir--; if(dir<0){dir=3;}
}
return dir;
}
}
//방문체크할 dir 과 격자의 type을 선언 class Lense {
boolean[] dir = new boolean[4];
String type;
public Lense(String type){
this.type=type;
}
}
|
cs |
//참고로 이 문제는 재귀함수로 풀어버리면, 테스트케이스 7번에서 런타임에러가뜬다.
너무 많이 깊어져서 StackOverflow를 뱉는것같다.
재귀함수로 풀지말고 While 루프로 리팩토링하자.
'알고리즘 > 프로그래머스 Level2' 카테고리의 다른 글
[프로그래머스,자바] Level2: 기능개발 (0) | 2021.09.25 |
---|---|
[프로그래머스,자바] Level2: 124 나라의 숫자 (0) | 2021.09.25 |
[프로그래머스,자바] Level2:멀쩡한 사각형 (0) | 2021.09.23 |
[프로그래머스,자바] Level2:오픈채팅방 (0) | 2021.09.22 |
[프로그래머스,자바] Level2: 문자열 압축 (0) | 2021.09.22 |