코딩테스트 연습 - 키패드 누르기
문제 설명
- 매개변수
- int[] numbers - 순서대로 누를 번호가 담긴 배열
- 배열 크기 1 ~ 1,000
- 원소 값 0 ~ 9 정수
- String hand - 오른손잡이 or 왼손잡이
- 리턴값 : 각 번호를 누른 엄지손가락 L, R 연속된 문자열
설계
- 키패드를 4 * 3 배열이라 생각하고 각 숫자의 row, col 값을 정한다.
- 0 → [3,1], 1 → [0,0], 5 → [1, 1], 7 → [2,0] …
- L → [3,0], R → [3,2]
- numbers 배열을 돌면서 숫자에 따라 왼손인지, 오른손인지 구한다.
- 1, 4, 7인 경우 → 왼손으로 입력한다. 왼손을 움직인 후의 위치를 저장한다.
- 3, 6, 9인 경우 → 오른손으로 입력한다. 오른손을 움직인 후의 위치를 저장한다.
- 2, 5, 8, 0인 경우
- 해당 숫자로부터 왼손, 오른손의 거리를 구한다.
- 거리가 더 짧은 손으로 입력한다. 움직인 후의 위치를 저장한다.
- 거리가 같다면 → hand 값의 손으로 입력한다. 움직인 후의 위치를 저장한다.
- 입력한 손을 String 문자열로 반환한다.
구현 방법
class Keypad
구현
- String name (키패드에 해당하는 숫자)
- int row, int col (row와 col 정보) → 클래스 내 변수는 private로 만들고, getter, setter를 만든다.
- Keypad 배열을 만들고 0 ~ 9 까지 숫자 이름과, 각각 행렬 정보를 넣어준다.
- 왼손(L), 오른손(R) 의 시작 행렬 정보도 Keypad 객체를 만들어 넣어준다.
- 번호를 보고 어느 손으로 입력할 지 정한다.
- 1, 4, 7 이거나 3, 6, 9인 경우는 입력할 손이 정해져있다.
- 2, 5, 8, 0의 경우, 왼손 오른손으로부터의 거리를 구해서 비교해야 한다. → 거리 구하는 것은
getDistance()
로 클래스 내 함수로 구현한다.
- 번호를 입력한 손은 StringBuilder에 하나씩 넣어준다.
- 번호를 입력했으면 입력한 손의 위치 정보를 숫자 위치로 업데이트 한다.
코드
class Keypad {
private String name;
private int row;
private int col;
public Keypad(String name, int row, int col) {
this.name = name;
this.row = row;
this.col = col;
}
public void setRowCol(int row, int col) {
this.row = row;
this.col = col;
}
public String getName() {
return name;
}
public int getRow() {
return row;
}
public int getCol() {
return col;
}
int getDistance(Keypad k) {
return Math.abs(k.row - this.row) + Math.abs(k.col - this.col);
}
}
class Solution {
public String solution(int[] numbers, String hand) {
StringBuilder sb = new StringBuilder();
Keypad[] keypad = new Keypad[10];
Keypad left = new Keypad("L", 3, 0);
Keypad right = new Keypad("R", 3, 2);
keypad[0] = new Keypad("0", 3, 1);
for (int idx = 1; idx < 10; idx++) {
for (int r = 0; r < 3; r++) {
for (int c = 0; c < 3; c++) {
keypad[idx] = new Keypad(String.valueOf(idx++), r, c);
}
}
}
for (int n : numbers) {
String next;
if (n == 1 | n == 4 | n == 7) {
next = left.getName();
left.setRowCol(n/3, 0);
} else if (n == 3 | n == 6 | n == 9) {
next = right.getName();
right.setRowCol(n/3 - 1, 2);
} else if (left.getDistance(keypad[n]) == right.getDistance(keypad[n])) {
next = hand.equals("right") ? right.getName() : left.getName();
} else
next =left.getDistance(keypad[n]) < right.getDistance(keypad[n]) ? left.getName() : right.getName();
if (next.equals(right.getName())) {
sb.append(right.getName());
right.setRowCol(keypad[n].getRow(), keypad[n].getCol());
} else {
sb.append(left.getName());
left.setRowCol(keypad[n].getRow(), keypad[n].getCol());
}
}
return sb.toString();
}
}
public class Main {
public static void main(String[] args) {
Solution sol = new Solution();
int[] numbers = {1, 3, 4, 5, 8, 2, 1, 4, 5, 9, 5};
String hand = "right";
System.out.println(sol.solution(numbers, hand));
}
}
시간 복잡도
어려웠던 점
- 처음에는 class를 만들어 번호 정보들을 저장하지 않았었다. 배열에도 넣어보려고 했고, map에도 정보를 저장해보려고 했으나, 키패드에 있는 모든 숫자와 위치 정보, 왼손 오른손의 위치 정보를 모두 저장하려면 class가 제일 낫겠다고 생각이 들었다.
- 클래스를 구현하고 흐름대로 코드를 짰을 때는 생각보다 깔끔하지 않고 반복되는 구문이 많았다. 객체를 사용할 때 장점을 살려보고자 getter, setter, 메서드 등을 구현하며 현 코드 상태로 정리가 되었다.