코드1
public String solution(int[] numbers, String hand) {
// 1,4,7 는 왼손
// 3,6,9는 오른손
// 2,5,8,0 까지의 거리가 같을때 hand 값으로 선택
// 현재 손가락의 위치를 담기 위한 변수
int right = 10;
int left = 12;
String answer = "";
for(int i=0; i<numbers.length; i++) {
// 0번일 경우 11의 값으로 변경
if(right == 0) {
right = 11;
}else if(left == 0) {
left = 11;
}
if(numbers[i]==1||numbers[i]==4||numbers[i]==7) {
answer += "L";
left = numbers[i];
continue;
}else if(numbers[i]==3||numbers[i]==6||numbers[i]==9) {
answer += "R";
right = numbers[i];
continue;
}else {
if(num(numbers[i],left) > num(numbers[i],right)) {
answer += "R";
right = numbers[i];
continue;
}else if(num(numbers[i],left) < num(numbers[i],right)) {
answer += "L";
left = numbers[i];
continue;
}else {
if(hand.equals("right")) {
answer += "R";
right = numbers[i];
continue;
}else {
answer += "L";
left = numbers[i];
continue;
}
}
}
}
return answer;
}
public int num(int a, int b) {
// 0번 버튼을 누를 경우 11로 변경
// 가운데 숫자들은 3씩 증가하기때문 2, 5, 8, 11
if(a==0) {
a = 11;
}
return (Math.abs(a-b)/3) + (Math.abs(a-b)%3);
}
풀이
규칙을 보면 세로의 열들 3씩 증가하게 되어있다.
맨 아래 열인 *,0,# 도 마찬가지로 3씩 증가시켜서 10, 11, 12의 숫자로 두고 풀이를 한다.
선택한 숫자 - 현재 눌려있는 숫자의 값을 3으로 나눈 나머지와 몫을 더하면 거리가 계산된다.
사실 처음에 시도했던 풀이방법은
키패드를 배열로 담아서 선택한 숫자와 배열의 값이 일치할 경우
기존에 눌려있는 숫자의 행,열 값과 선택한 숫자의 행,열 값을 계산해서 거리를 구하려고 했는데
테스트 케이스 실패가 있어서 방식을 변경했는데,
풀이 방법은 맞는 것 같으니 다시한번 배열로 풀어보고 올려야겠다. (아래 배열풀이 추가)
코드2 (배열 이용) 성능 저하 버전 (아래의 코드3에서 성능 향상)
class Solution {
public String solution(int[] numbers, String hand) {
//1,4,7은 left 즉,keyPad의 0열은 left
//3,6,9는 right 즉,keyPad의 2열은 right
//거리가 같은 결우 hand 기준으로 값 정의
//숫자 키패드 배열로 변환
int[][] keyPad = {{1,2,3},{4,5,6},{7,8,9},{10,0,12}};
//초기 왼손 위치
int[] lHand = {3,0};
//초기 오른손 위치
int[] rHand = {3,2};
String answer = "";
for (int i = 0; i < numbers.length; i++) {
loop:
for (int row = 0; row < keyPad.length; row++) { //키 패드 행
for (int col = 0; col < keyPad[0].length; col++) { //키 패드 열
if (numbers[i] == keyPad[row][col]) {
if (col == 0) { //왼손 1,4,7
lHand[0] = row;
lHand[1] = col;
answer += "L";
break loop;
} else if (col == 2) { //오른손 3,6,9
rHand[0] = row;
rHand[1] = col;
answer += "R";
break loop;
} else { // 가운데 2,5,8,0 일 경우
if (abs(lHand[0], row, lHand[1], col) < abs(rHand[0], row, rHand[1], col)) { //왼손이랑 가까운 경우
lHand[0] = row;
lHand[1] = col;
answer += "L";
break loop;
} else if (abs(lHand[0], row, lHand[1], col) > abs(rHand[0], row, rHand[1], col)) { //오른손이랑 가까운 경우
rHand[0] = row;
rHand[1] = col;
answer += "R";
break loop;
} else { // 양손 거리 같은 경우 주로 쓰는 손으로 선택
if (hand.equals("left")) {
lHand[0] = row;
lHand[1] = col;
answer += "L";
} else {
rHand[0] = row;
rHand[1] = col;
answer += "R";
}
break loop;
}
}
}
}
}
}
return answer;
}
public int abs(int a, int row, int b, int col) {
return Math.abs(a-row) + Math.abs(b-col);
}
public static void main(String[] args) {
Solution sol = new Solution();
int[] arr = {7, 0, 8, 2, 8, 3, 1, 5, 7, 6, 2};
System.out.println(sol.solution(arr, "left"));
}
}
Math.abs(col-left[0])+Math.abs(row-left[1]) // (선택 숫자 행 - 기존숫자 행) + (선택 숫자 열 - 기존숫자 열)
처리 속도는 방법2 배열을 이용했을 때가 빠르다.
더 짧고 쉽게 풀 수 있는 방법은 떠오르질 않는다...
코드3 (배열 이용) 성능 향상 버전
코드2의 방법에서 성능의 문제점은 String는 변수의 불변성으로 연산자 +를 이용한 문자열 합치기를 하면
내부적으로 새로운 String 객체를 생성해 텍스트를 붙인다.
때문에 new 객체 선언으로 메모리 낭비가 일어나서 서능이 저하된다.
append로 성능향상
class Solution {
public String solution(int[] numbers, String hand) {
//1,4,7은 left 즉,keyPad의 0열은 left
//3,6,9는 right 즉,keyPad의 2열은 right
//거리가 같은 결우 hand 기준으로 값 정의
//숫자 키패드 배열로 변환
int[][] keyPad = {{1,2,3},{4,5,6},{7,8,9},{10,0,12}};
//초기 왼손 위치
int[] lHand = {3,0};
//초기 오른손 위치
int[] rHand = {3,2};
StringBuilder answer = new StringBuilder();
for (int number : numbers) {
loop:
for (int row = 0; row < keyPad.length; row++) { //키 패드 행
for (int col = 0; col < keyPad[0].length; col++) { //키 패드 열
if (number == keyPad[row][col]) {
if (col == 0) { //왼손 1,4,7
lHand[0] = row;
lHand[1] = col;
answer.append("L");
break loop;
} else if (col == 2) { //오른손 3,6,9
rHand[0] = row;
rHand[1] = col;
answer.append("R");
break loop;
} else { // 가운데 2,5,8,0 일 경우
if (abs(lHand[0], row, lHand[1], col) < abs(rHand[0], row, rHand[1], col)) { //왼손이랑 가까운 경우
lHand[0] = row;
lHand[1] = col;
answer.append("L");
break loop;
} else if (abs(lHand[0], row, lHand[1], col) > abs(rHand[0], row, rHand[1], col)) { //오른손이랑 가까운 경우
rHand[0] = row;
rHand[1] = col;
answer.append("R");
break loop;
} else { // 양손 거리 같은 경우 주로 쓰는 손으로 선택
if (hand.equals("left")) {
lHand[0] = row;
lHand[1] = col;
answer.append("L");
} else {
rHand[0] = row;
rHand[1] = col;
answer.append("R");
}
break loop;
}
}
}
}
}
}
return answer.toString();
}
public int abs(int a, int row, int b, int col) {
return Math.abs(a-row) + Math.abs(b-col);
}
public static void main(String[] args) {
Solution sol = new Solution();
int[] arr = {7, 0, 8, 2, 8, 3, 1, 5, 7, 6, 2};
System.out.println(sol.solution(arr, "left"));
}
}
[프로그래머스][Level1][예산] (0) | 2021.03.17 |
---|---|
[프로그래머스][Level1][실패율] (0) | 2021.03.16 |
[프로그래머스][Level1][1차 비밀지도] (0) | 2021.03.12 |
[프로그래머스][Level1][포켓몬] (0) | 2021.03.12 |
[프로그래머스][Level1][(월간 코드 챌린지 시즌1)두 개 뽑아서 더하기] (0) | 2021.03.11 |