코딩테스트/Java

(2018카카오) 자물쇠와 열쇠 Java

SK_MOUSE 2021. 1. 28. 15:15

https://programmers.co.kr/learn/courses/30/lessons/60059

  1. Lock의 약 3배크기의 그리드를 준비한다.
  2. Lock을 그리드의 중앙으로 복사한다.
  3. Key값을 각각의 Lock의 꼭짓점부터 순회한다.
  4. 더불어 Key를 회전(rotate)시키면서 탐색한다.
  5. 탐색할시에 Lock위치에 해당하는 인덱스의 값이 모두 1이어야 Lock이 딱 맞는걸로 판별된다.

그리드 예시1 https://www.youtube.com/watch?v=I1App3qLi6o

위의 그림처럼 키의값이 겹치면 1이 아닌것을 return하게 된다.

 

 

dfs방식 : boolean isOk값을 true냐 false냐로 판단한다.

public void dfs(int[][]key, int [][] lock, int cnt) { ​​​​​​​​check(key, lock, 0, 0); ​​​​​​​​if(isOk) return; ​​​​​​​​if(cnt >= 4) return; ​​​​​​​​int[][] temp = rotate(key);//키회전시킨걸로 탐색 ​​​​​​​​dfs(temp, lock, cnt+1);//rotate ++; ​​​​}

위처럼, key값을 받고 lock에 대하여 check를 한다음, isOk가 true인 경우에는 더이상 탐색하지 않고 true반환.

cnt는 rotate(회전)을 하기 위해서 사용하는 변수다.

그리고 회전시킨key를 다시 dfs재귀호출한다.

 

  • 회전

rotate는 이중for문을 이용한다. 

 

회전시 i값은 j값이되고 j값은 역배열된다.

public int[][] rotate(int [][] key) { //회전 ​​​​​​​​int len = key.length; ​​​​​​​​int[][] temp = new int[len][len]; ​​​​​​​​for(int i=0; i<len; i++) { ​​​​​​​​​​​​for(int j=0; j<len; j++) { ​​​​​​​​​​​​​​​​temp[i][j] = key[len-j-1][i]; ​​​​​​​​​​​​} ​​​​​​​​} ​​​​​​​​return temp; ​​​​}
  • check
public void check(int[][] key, int[][] lock, int x, int y) { ​​​​​​​​if(isOk) return; ​​​​​​​​if(y+key.length>lock.length) {//세로로 순환하고 가로값 증가하면서 ​​​​​​​​​​​​y=0;//아래로가다가 다시 위로 ​​​​​​​​​​​​x++;//오른쪽(x)으로 y++하면서 탐색 ​​​​​​​​} ​​​​​​​​if(x+key.length>lock.length) return;//x값 다 돌았으면 종료. ​​​​​​​​int[][] copyLock = new int[lock.length][lock.length]; ​​​​​​​​for(int i=0; i<lock.length; i++) { ​​​​​​​​​​​​copyLock[i] = lock[i].clone(); ​​​​​​​​} ​​​​​​​​//탐색시작 ​​​​​​​​boolean isFail = false;//실패냐? ​​​​​​​​loop: ​​​​​​​​for(int i=0; i<key.length; i++) { ​​​​​​​​​​​​for(int j=0; j<key.length; j++) { ​​​​​​​​​​​​​​​​if(key[i][j]==1) {//key가 1인 부분이 ​​​​​​​​​​​​​​​​​​​​if(copyLock[i+x][j+y]==1) {//같이 1이면 실패 ​​​​​​​​​​​​​​​​​​​​​​​​isFail = true; ​​​​​​​​​​​​​​​​​​​​​​​​break loop; ​​​​​​​​​​​​​​​​​​​​} ​​​​​​​​​​​​​​​​​​​​copyLock[i+x][j+y] = key[i][j]; ​​​​​​​​​​​​​​​​} ​​​​​​​​​​​​} ​​​​​​​​} ​​​​​​​​if(!isFail) { ​​​​​​​​​​​​loop: ​​​​​​​​​​​​for(int i=0; i<lock.length/3; i++) { ​​​​​​​​​​​​​​​​for(int j=0; j<lock.length/3; j++) { ​​​​​​​​​​​​​​​​​​​​if(copyLock[i+lock.length/3][j+lock.length/3] != 1) { ​​​​​​​​​​​​​​​​​​​​​​​​isFail = true; ​​​​​​​​​​​​​​​​​​​​​​​​break loop; ​​​​​​​​​​​​​​​​​​​​} ​​​​​​​​​​​​​​​​} ​​​​​​​​​​​​} ​​​​​​​​} ​​​​​​​​if(!isFail) { ​​​​​​​​​​​​isOk = true; ​​​​​​​​​​​​return; ​​​​​​​​} ​​​​​​​​check(key, lock, x, y+1);//다음줄 y값 실행 ​​​​}

재귀적으로 check를 호출하여 한 행씩 검사한다.

 

 

전체코드

class Solution { ​​​​static boolean isOk = false; ​​​​public boolean solution(int[][] key, int[][] lock) { ​​​​​​​​int len = lock.length; ​​​​​​​​//3배 확장 후 중앙으로 옮기기 ​​​​​​​​int[][] copyLock = new int[len*3][len*3]; ​​​​​​​​for(int i=0; i<len; i++) { ​​​​​​​​​​​​for(int j=0; j<len; j++) { ​​​​​​​​​​​​​​​​copyLock[i+len][j+len] = lock[i][j]; ​​​​​​​​​​​​} ​​​​​​​​} ​​​​​​​​dfs(key, copyLock, 0); ​​​​​​​​return isOk; ​​​​} ​​​​public void dfs(int[][]key, int [][] lock, int cnt) { ​​​​​​​​check(key, lock, 0, 0); ​​​​​​​​if(isOk) return; ​​​​​​​​if(cnt >= 4) return; ​​​​​​​​int[][] temp = rotate(key);//키회전시킨걸로 탐색 ​​​​​​​​dfs(temp, lock, cnt+1);//rotate ++; ​​​​} ​​​​public void check(int[][] key, int[][] lock, int x, int y) { ​​​​​​​​if(isOk) return; ​​​​​​​​if(y+key.length>lock.length) { ​​​​​​​​​​​​y=0; ​​​​​​​​​​​​x++; ​​​​​​​​} ​​​​​​​​if(x+key.length>lock.length) return; ​​​​​​​​int[][] copyLock = new int[lock.length][lock.length]; ​​​​​​​​for(int i=0; i<lock.length; i++) { ​​​​​​​​​​​​copyLock[i] = lock[i].clone(); ​​​​​​​​} ​​​​​​​​boolean isFail = false; ​​​​​​​​loop: ​​​​​​​​for(int i=0; i<key.length; i++) { ​​​​​​​​​​​​for(int j=0; j<key.length; j++) { ​​​​​​​​​​​​​​​​if(key[i][j]==1) { ​​​​​​​​​​​​​​​​​​​​if(copyLock[i+x][j+y]==1) { ​​​​​​​​​​​​​​​​​​​​​​​​isFail = true; ​​​​​​​​​​​​​​​​​​​​​​​​break loop; ​​​​​​​​​​​​​​​​​​​​} ​​​​​​​​​​​​​​​​​​​​copyLock[i+x][j+y] = key[i][j]; ​​​​​​​​​​​​​​​​} ​​​​​​​​​​​​} ​​​​​​​​} ​​​​​​​​if(!isFail) { ​​​​​​​​​​​​loop: ​​​​​​​​​​​​for(int i=0; i<lock.length/3; i++) { ​​​​​​​​​​​​​​​​for(int j=0; j<lock.length/3; j++) { ​​​​​​​​​​​​​​​​​​​​if(copyLock[i+lock.length/3][j+lock.length/3] != 1) { ​​​​​​​​​​​​​​​​​​​​​​​​isFail = true; ​​​​​​​​​​​​​​​​​​​​​​​​break loop; ​​​​​​​​​​​​​​​​​​​​} ​​​​​​​​​​​​​​​​} ​​​​​​​​​​​​} ​​​​​​​​} ​​​​​​​​if(!isFail) { ​​​​​​​​​​​​isOk = true; ​​​​​​​​} ​​​​​​​​check(key, lock, x, y+1); ​​​​} ​​​​public int[][] rotate(int [][] key) { //회전 ​​​​​​​​int len = key.length; ​​​​​​​​int[][] temp = new int[len][len]; ​​​​​​​​for(int i=0; i<len; i++) { ​​​​​​​​​​​​for(int j=0; j<len; j++) { ​​​​​​​​​​​​​​​​temp[i][j] = key[len-j-1][i]; ​​​​​​​​​​​​} ​​​​​​​​} ​​​​​​​​return temp; ​​​​} }

 

반응형