-
[프로그래머스][lv2] 영어 끝말잇기 Java알고리즘 2023. 2. 2. 16:44
문제 설명
1부터 n까지 번호가 붙어있는 n명의 사람이 영어 끝말잇기를 하고 있습니다. 영어 끝말잇기는 다음과 같은 규칙으로 진행됩니다.
- 1번부터 번호 순서대로 한 사람씩 차례대로 단어를 말합니다.
- 마지막 사람이 단어를 말한 다음에는 다시 1번부터 시작합니다.
- 앞사람이 말한 단어의 마지막 문자로 시작하는 단어를 말해야 합니다.
- 이전에 등장했던 단어는 사용할 수 없습니다.
- 한 글자인 단어는 인정되지 않습니다.
다음은 3명이 끝말잇기를 하는 상황을 나타냅니다.
tank → kick → know → wheel → land → dream → mother → robot → tank
위 끝말잇기는 다음과 같이 진행됩니다.
- 1번 사람이 자신의 첫 번째 차례에 tank를 말합니다.
- 2번 사람이 자신의 첫 번째 차례에 kick을 말합니다.
- 3번 사람이 자신의 첫 번째 차례에 know를 말합니다.
- 1번 사람이 자신의 두 번째 차례에 wheel을 말합니다.
- (계속 진행)
끝말잇기를 계속 진행해 나가다 보면, 3번 사람이 자신의 세 번째 차례에 말한 tank 라는 단어는 이전에 등장했던 단어이므로 탈락하게 됩니다.
사람의 수 n과 사람들이 순서대로 말한 단어 words 가 매개변수로 주어질 때, 가장 먼저 탈락하는 사람의 번호와 그 사람이 자신의 몇 번째 차례에 탈락하는지를 구해서 return 하도록 solution 함수를 완성해주세요.
제한 사항
- 끝말잇기에 참여하는 사람의 수 n은 2 이상 10 이하의 자연수입니다.
- words는 끝말잇기에 사용한 단어들이 순서대로 들어있는 배열이며, 길이는 n 이상 100 이하입니다.
- 단어의 길이는 2 이상 50 이하입니다.
- 모든 단어는 알파벳 소문자로만 이루어져 있습니다.
- 끝말잇기에 사용되는 단어의 뜻(의미)은 신경 쓰지 않으셔도 됩니다.
- 정답은 [ 번호, 차례 ] 형태로 return 해주세요.
- 만약 주어진 단어들로 탈락자가 생기지 않는다면, [0, 0]을 return 해주세요.
입출력 예
입출력 예 설명
입출력 예 #13명의 사람이 끝말잇기에 참여하고 있습니다.
- 1번 사람 : tank, wheel, mother
- 2번 사람 : kick, land, robot
- 3번 사람 : know, dream, tank
와 같은 순서로 말을 하게 되며, 3번 사람이 자신의 세 번째 차례에 말한 tank라는 단어가 1번 사람이 자신의 첫 번째 차례에 말한 tank와 같으므로 3번 사람이 자신의 세 번째 차례로 말을 할 때 처음 탈락자가 나오게 됩니다.
입출력 예 #25명의 사람이 끝말잇기에 참여하고 있습니다.
- 1번 사람 : hello, recognize, gather
- 2번 사람 : observe, encourage, refer
- 3번 사람 : effect, ensure, reference
- 4번 사람 : take, establish, estimate
- 5번 사람 : either, hang, executive
와 같은 순서로 말을 하게 되며, 이 경우는 주어진 단어로만으로는 탈락자가 발생하지 않습니다. 따라서 [0, 0]을 return하면 됩니다.
입출력 예 #32명의 사람이 끝말잇기에 참여하고 있습니다.
- 1번 사람 : hello, even, now, draw
- 2번 사람 : one, never, world
와 같은 순서로 말을 하게 되며, 1번 사람이 자신의 세 번째 차례에 'r'로 시작하는 단어 대신, n으로 시작하는 now를 말했기 때문에 이때 처음 탈락자가 나오게 됩니다.
내가 해결한 방식
문제에서 친절하게 3가지 경우를 모두 알려줘서 그에 맞게 로직을 짜기만 하면 되는 문제였다.
처음 이 문제를 풀 때는 이차원 배열을 사용하려고 했었는데 return 자료형이 int[]여서 이차원 배열을 사용하지 않았고, 실제로 이차원 배열로 푸는 문제가 아니었다.
문제의 규칙성을 좌표개념으로 접근했다. 예를 들어
- 1번 사람 : tank, wheel, mother - 2번 사람 : kick, land, robot - 3번 사람 : know, dream, `tank`
위와 같은 경우를 좌표 개념으로 생각하면
1,1 2,1 3,1 1,2 2,2 3,2 1,3 2,3 3,3
위와 같다. 이때 규칙성을 발견할 수 있는데, x좌표는 n명일 때 1~n까지, 그리고 x좌표가 n 값이 되었을 때 x좌표를 1로 초기화하고, y좌표를 +1 해준다.
위 문제의 경우의 수는 세가지이다.
- 주어진 words 배열에서 같은 문자열이 존재할 때 그 문자열의 좌표 위치를 반환한다.
- 만약 앞 문자열의 끝 문자와 현재 문자열의 첫번 째 문자가 서로 다를 때 현재 좌표를 반환한다.
- 위 두가지 경우가 모두 해당하지 않을 때는 정상적인 끝말잇기를 마쳤다는 의미이므로 [0,0] 좌표를 반환한다.
첫번 째 경우는 HashMap을 사용해서 key 값에다가 +1을 해준다. 그러다가 words 배열 내에서 동일한 key 값이 존재하게 되면 해당하는 key 값은 value = 2가 되므로 그 당시의 좌표를 반환해주면 된다. 이에 대한 로직은 아래와 같이 구현했다.
int lt = 1, rt = 1; //words 내에 같은 문자열이 나올 때 for(String x : words){ map.put(x, map.getOrDefault(x, 0)+1); if(map.get(x) == 2){ answer[0] = lt; answer[1] = rt; return answer; } if(lt == n) { lt = 0; rt++; } lt++; }
그 다음으로 두번 째 경우인 앞 문자열의 끝 문자가 현재 문자열의 첫번 째 문자와 다를 때 현재 좌표를 반환해주는 로직은 아래와 같다.
lt = 1; rt = 1; // 앞 문자열의 끝 글자와 현재 문자열의 첫 글자가 같지 않을 때 for(int i = 1; i < words.length; i++){ char t = words[i-1].charAt(words[i-1].length()-1); char t2 = words[i].charAt(0); if(lt == n){ lt = 0; rt++; } lt++; if(t != t2){ answer[0] = lt; answer[1] = rt; return answer; } }
위 두 로직을 보면 각각의 조건에 해당하는 경우에 바로 return answer;를 해준다.
왜냐하면 위 두 조건을 해당한다는 의미는 끝말잇기의 탈락자가 발생했다는 의미이므로 더 진행할 필요가 없기 때문이다.
마지막으로 세번 째 조건인데 이 조건은 간단하다.
처음 answer 값 0 인덱스와 1 인덱스 모두 0으로 초기화 시켜놓으면 된다.
이 상태에서 위 두 조건을 만족하지 않고 for문을 빠져나오면 answer의 0번 째 인덱스와 1번 째 인덱스는 0으로 유지될 것이기 때문이다.
//위 두 로직을 만족하지 않았을 때 int[] answer = new int[2]; answer[0] = 0; answer[1] = 0; return answer;
아래 코드는 intellij로 문제를 해결한 코드
package programmers.lv2; import com.fasterxml.jackson.core.JsonToken; import java.util.HashMap; import java.util.Scanner; public class EnglishFollowUp { public int[] solution(int n, String[] words) { int[] answer = new int[2]; answer[0] = 0; answer[1] = 0; HashMap<String, Integer> map = new HashMap<>(); int lt = 1, rt = 1; //words 내에 같은 문자열이 나올 때 for(String x : words){ map.put(x, map.getOrDefault(x, 0)+1); if(map.get(x) == 2){ answer[0] = lt; answer[1] = rt; System.out.println(answer[0] + "" + answer[1]); return answer; } if(lt == n) { lt = 0; rt++; } lt++; } lt = 1; rt = 1; // 앞 문자열의 끝 글자와 현재 글자의 첫 글자가 같지 않을 때 for(int i = 1; i < words.length; i++){ char t = words[i-1].charAt(words[i-1].length()-1); char t2 = words[i].charAt(0); if(lt == n){ lt = 0; rt++; } lt++; if(t != t2){ answer[0] = lt; answer[1] = rt; System.out.println(answer[0] + "" + answer[1]); return answer; } } // System.out.println(answer[0] + "" + answer[1]); return answer; } public static void main(String[] args) { EnglishFollowUp T = new EnglishFollowUp(); Scanner in = new Scanner(System.in); int n = in.nextInt(); String[] words = {"hello", "observe", "effect", "take", "kither", "kecognize", "kncourage", "ensure", "establish", "hang", "gather", "refer", "reference", "estimate", "kxecutive"}; System.out.println(T.solution(n, words)); } }
아래 코드는 프로그래머스에 제출한 코드
import java.util.HashMap; class Solution { public int[] solution(int n, String[] words) { int[] answer = new int[2]; answer[0] = 0; answer[1] = 0; HashMap<String, Integer> map = new HashMap<>(); int lt = 1, rt = 1; int cnt = 0; //words 내에 같은 문자열이 나올 때 for(String x : words){ map.put(x, map.getOrDefault(x, 0)+1); if(map.get(x) == 2){ answer[0] = lt; answer[1] = rt; // System.out.println(answer[0] + "" + answer[1]); return answer; } if(lt == n) { lt = 0; rt++; } lt++; } lt = 1; rt = 1; for(int i = 1; i < words.length; i++){ char t = words[i-1].charAt(words[i-1].length()-1); char t2 = words[i].charAt(0); if(lt == n){ lt = 0; rt++; } lt++; if(t != t2){ answer[0] = lt; answer[1] = rt; // System.out.println(answer[0] + "" + answer[1]); return answer; } } // System.out.println(answer[0] + "" + answer[1]); return answer; } }
아쉬운 점
- 이 문제를 해결하는데 자그마치 두시간이 걸렸다. 코딩테스트는 두시간 동안 3~4 문제를 풀어야 한다고 알고있는데 염려스럽다. 빨리 풀려고 도전해봤지만 스트레스만 쌓였다.. 자료구조 지식과 알고리즘 지식 그리고 부족한 문제풀이 경험 때문이라고 생각한다. 이를 개선하기 위해 자료구조 지식을 먼저 다져놓고 알고리즘 문제를 풀어야할 것 같다.
- 수시로 콘솔에 값을 출력해가면서 답을 찾아나갔다는 것이다. 이는 정답을 맞추기 위해 코드로 노동을 하는 기분이고, 무식한 방법으로 풀고 있다는 느낌을 준다.
- 코드가 난해하고 지저분하다…
다른 사람의 풀이
import java.util.HashSet; class Solution { public int[] solution(int n, String[] words) { int[] answer = { 0, 0 }; char chEnd = words[0].charAt(words[0].length() - 1); char chStart; System.out.print(chEnd + " "); HashSet<String> log = new HashSet<>(); log.add(words[0]); for (int i = 1; i < words.length; i++) { chStart = words[i].charAt(0); log.add(words[i]); if (chEnd != chStart || log.size() != i + 1) { System.out.print(i + 1 + "!"); answer[0] = (i % n)+1; answer[1] = (i / n) + 1; break; } chEnd = words[i].charAt(words[i].length() - 1); System.out.print(chEnd + " "); } System.out.println(); System.out.println("(" + answer[0] + ", " + answer[1] + ")"); return answer; } }
프로그래머스의 어떤 분이 이 문제를 해결한 방식이다.
- 중복된 문자열이 존재하는 경우는 HashSet 클래스를 사용해서 저장되지 않도록한다. 해당 문자열이 저장되지 않았으므로 log.size는 ≠ i + 1이 아니게 될 것이다.
- 앞 문자열의 마지막 글자는 chEnd 변수로, 현재 문자열의 첫번 째 글자는 chStart 변수로 초기화 시켜주었다.
- 만약 위 두 조건 중 하나라도 만족할 시에는
answer[0] = (i % n) + 1; answer[1] = (i / n) + 1;
로 처리해주었다. 위 로직을 출력한 예시는 아래와 같다
i = 1 i%n+1 = 2 i = 2 i%n+1 = 3 i = 3 i%n+1 = 1 i = 4 i%n+1 = 2 i = 5 i%n+1 = 3 i = 6 i%n+1 = 1 i = 7 i%n+1 = 2 i = 8 i%n+1 = 3 // i = 8일 때 tank가 두번 등장하므로 answer[0] = 3이 담긴다. //(i/n) + 1도 위와 같은 형식이지만 나누기라는 점만 다르다.
문제를 풀 때 나와 다른 점.
- HashSet으로 중복 문자열을 체크했다.
- 하나의 for문 안에 두 조건을 모두 넣어서 코드가 더 간략하다.
- 코드가 더 간략해서 가독성 + 이해하기 좋다.
- answer[0], answer[1]에 값을 넣는 방식을 나와 다른 방식의 규칙성(i%n+1 또는 i/n+1)을 사용하였다.
놀라운 점은 내가 만든 코드가 더 빠른 속도로 문제를 해결했다는 점이다. 내가 푼 코드는
의 속도로 문제를 해결했고 다른 사람이 푼 코드는
속도로 내가 더 빠른 속도로 문제를 해결했다. 이를 보았을 때 나도 힌트 없이 내 힘으로 문제를 해결했고 통과 속도도 더 빨랐다. 그러므로 스스로 문제를 해결했고 좋은 결과를 낳았다는 점에서 스스로를 대견하다고 생각하면 좋을 것 같다.
문제 설명
1부터 n까지 번호가 붙어있는 n명의 사람이 영어 끝말잇기를 하고 있습니다. 영어 끝말잇기는 다음과 같은 규칙으로 진행됩니다.
- 1번부터 번호 순서대로 한 사람씩 차례대로 단어를 말합니다.
- 마지막 사람이 단어를 말한 다음에는 다시 1번부터 시작합니다.
- 앞사람이 말한 단어의 마지막 문자로 시작하는 단어를 말해야 합니다.
- 이전에 등장했던 단어는 사용할 수 없습니다.
- 한 글자인 단어는 인정되지 않습니다.
다음은 3명이 끝말잇기를 하는 상황을 나타냅니다.
tank → kick → know → wheel → land → dream → mother → robot → tank
위 끝말잇기는 다음과 같이 진행됩니다.
- 1번 사람이 자신의 첫 번째 차례에 tank를 말합니다.
- 2번 사람이 자신의 첫 번째 차례에 kick을 말합니다.
- 3번 사람이 자신의 첫 번째 차례에 know를 말합니다.
- 1번 사람이 자신의 두 번째 차례에 wheel을 말합니다.
- (계속 진행)
끝말잇기를 계속 진행해 나가다 보면, 3번 사람이 자신의 세 번째 차례에 말한 tank 라는 단어는 이전에 등장했던 단어이므로 탈락하게 됩니다.
사람의 수 n과 사람들이 순서대로 말한 단어 words 가 매개변수로 주어질 때, 가장 먼저 탈락하는 사람의 번호와 그 사람이 자신의 몇 번째 차례에 탈락하는지를 구해서 return 하도록 solution 함수를 완성해주세요.
제한 사항
- 끝말잇기에 참여하는 사람의 수 n은 2 이상 10 이하의 자연수입니다.
- words는 끝말잇기에 사용한 단어들이 순서대로 들어있는 배열이며, 길이는 n 이상 100 이하입니다.
- 단어의 길이는 2 이상 50 이하입니다.
- 모든 단어는 알파벳 소문자로만 이루어져 있습니다.
- 끝말잇기에 사용되는 단어의 뜻(의미)은 신경 쓰지 않으셔도 됩니다.
- 정답은 [ 번호, 차례 ] 형태로 return 해주세요.
- 만약 주어진 단어들로 탈락자가 생기지 않는다면, [0, 0]을 return 해주세요.
입출력 예
입출력 예 설명
입출력 예 #13명의 사람이 끝말잇기에 참여하고 있습니다.
- 1번 사람 : tank, wheel, mother
- 2번 사람 : kick, land, robot
- 3번 사람 : know, dream, tank
와 같은 순서로 말을 하게 되며, 3번 사람이 자신의 세 번째 차례에 말한 tank라는 단어가 1번 사람이 자신의 첫 번째 차례에 말한 tank와 같으므로 3번 사람이 자신의 세 번째 차례로 말을 할 때 처음 탈락자가 나오게 됩니다.
입출력 예 #25명의 사람이 끝말잇기에 참여하고 있습니다.
- 1번 사람 : hello, recognize, gather
- 2번 사람 : observe, encourage, refer
- 3번 사람 : effect, ensure, reference
- 4번 사람 : take, establish, estimate
- 5번 사람 : either, hang, executive
와 같은 순서로 말을 하게 되며, 이 경우는 주어진 단어로만으로는 탈락자가 발생하지 않습니다. 따라서 [0, 0]을 return하면 됩니다.
입출력 예 #32명의 사람이 끝말잇기에 참여하고 있습니다.
- 1번 사람 : hello, even, now, draw
- 2번 사람 : one, never, world
와 같은 순서로 말을 하게 되며, 1번 사람이 자신의 세 번째 차례에 'r'로 시작하는 단어 대신, n으로 시작하는 now를 말했기 때문에 이때 처음 탈락자가 나오게 됩니다.
내가 해결한 방식
문제에서 친절하게 3가지 경우를 모두 알려줘서 그에 맞게 로직을 짜기만 하면 되는 문제였다.
처음 이 문제를 풀 때는 이차원 배열을 사용하려고 했었는데 return 자료형이 int[]여서 이차원 배열을 사용하지 않았고, 실제로 이차원 배열로 푸는 문제가 아니었다.
문제의 규칙성을 좌표개념으로 접근했다. 예를 들어
- 1번 사람 : tank, wheel, mother - 2번 사람 : kick, land, robot - 3번 사람 : know, dream, `tank`
위와 같은 경우를 좌표 개념으로 생각하면
1,1 2,1 3,1 1,2 2,2 3,2 1,3 2,3 3,3
위와 같다. 이때 규칙성을 발견할 수 있는데, x좌표는 n명일 때 1~n까지, 그리고 x좌표가 n 값이 되었을 때 x좌표를 1로 초기화하고, y좌표를 +1 해준다.
위 문제의 경우의 수는 세가지이다.
- 주어진 words 배열에서 같은 문자열이 존재할 때 그 문자열의 좌표 위치를 반환한다.
- 만약 앞 문자열의 끝 문자와 현재 문자열의 첫번 째 문자가 서로 다를 때 현재 좌표를 반환한다.
- 위 두가지 경우가 모두 해당하지 않을 때는 정상적인 끝말잇기를 마쳤다는 의미이므로 [0,0] 좌표를 반환한다.
첫번 째 경우는 HashMap을 사용해서 key 값에다가 +1을 해준다. 그러다가 words 배열 내에서 동일한 key 값이 존재하게 되면 해당하는 key 값은 value = 2가 되므로 그 당시의 좌표를 반환해주면 된다. 이에 대한 로직은 아래와 같이 구현했다.
int lt = 1, rt = 1; //words 내에 같은 문자열이 나올 때 for(String x : words){ map.put(x, map.getOrDefault(x, 0)+1); if(map.get(x) == 2){ answer[0] = lt; answer[1] = rt; return answer; } if(lt == n) { lt = 0; rt++; } lt++; }
그 다음으로 두번 째 경우인 앞 문자열의 끝 문자가 현재 문자열의 첫번 째 문자와 다를 때 현재 좌표를 반환해주는 로직은 아래와 같다.
lt = 1; rt = 1; // 앞 문자열의 끝 글자와 현재 문자열의 첫 글자가 같지 않을 때 for(int i = 1; i < words.length; i++){ char t = words[i-1].charAt(words[i-1].length()-1); char t2 = words[i].charAt(0); if(lt == n){ lt = 0; rt++; } lt++; if(t != t2){ answer[0] = lt; answer[1] = rt; return answer; } }
위 두 로직을 보면 각각의 조건에 해당하는 경우에 바로 return answer;를 해준다.
왜냐하면 위 두 조건을 해당한다는 의미는 끝말잇기의 탈락자가 발생했다는 의미이므로 더 진행할 필요가 없기 때문이다.
마지막으로 세번 째 조건인데 이 조건은 간단하다.
처음 answer 값 0 인덱스와 1 인덱스 모두 0으로 초기화 시켜놓으면 된다.
이 상태에서 위 두 조건을 만족하지 않고 for문을 빠져나오면 answer의 0번 째 인덱스와 1번 째 인덱스는 0으로 유지될 것이기 때문이다.
//위 두 로직을 만족하지 않았을 때 int[] answer = new int[2]; answer[0] = 0; answer[1] = 0; return answer;
아래 코드는 intellij로 문제를 해결한 코드
package programmers.lv2; import com.fasterxml.jackson.core.JsonToken; import java.util.HashMap; import java.util.Scanner; public class EnglishFollowUp { public int[] solution(int n, String[] words) { int[] answer = new int[2]; answer[0] = 0; answer[1] = 0; HashMap<String, Integer> map = new HashMap<>(); int lt = 1, rt = 1; //words 내에 같은 문자열이 나올 때 for(String x : words){ map.put(x, map.getOrDefault(x, 0)+1); if(map.get(x) == 2){ answer[0] = lt; answer[1] = rt; System.out.println(answer[0] + "" + answer[1]); return answer; } if(lt == n) { lt = 0; rt++; } lt++; } lt = 1; rt = 1; // 앞 문자열의 끝 글자와 현재 글자의 첫 글자가 같지 않을 때 for(int i = 1; i < words.length; i++){ char t = words[i-1].charAt(words[i-1].length()-1); char t2 = words[i].charAt(0); if(lt == n){ lt = 0; rt++; } lt++; if(t != t2){ answer[0] = lt; answer[1] = rt; System.out.println(answer[0] + "" + answer[1]); return answer; } } // System.out.println(answer[0] + "" + answer[1]); return answer; } public static void main(String[] args) { EnglishFollowUp T = new EnglishFollowUp(); Scanner in = new Scanner(System.in); int n = in.nextInt(); String[] words = {"hello", "observe", "effect", "take", "kither", "kecognize", "kncourage", "ensure", "establish", "hang", "gather", "refer", "reference", "estimate", "kxecutive"}; System.out.println(T.solution(n, words)); } }
아래 코드는 프로그래머스에 제출한 코드
import java.util.HashMap; class Solution { public int[] solution(int n, String[] words) { int[] answer = new int[2]; answer[0] = 0; answer[1] = 0; HashMap<String, Integer> map = new HashMap<>(); int lt = 1, rt = 1; int cnt = 0; //words 내에 같은 문자열이 나올 때 for(String x : words){ map.put(x, map.getOrDefault(x, 0)+1); if(map.get(x) == 2){ answer[0] = lt; answer[1] = rt; // System.out.println(answer[0] + "" + answer[1]); return answer; } if(lt == n) { lt = 0; rt++; } lt++; } lt = 1; rt = 1; for(int i = 1; i < words.length; i++){ char t = words[i-1].charAt(words[i-1].length()-1); char t2 = words[i].charAt(0); if(lt == n){ lt = 0; rt++; } lt++; if(t != t2){ answer[0] = lt; answer[1] = rt; // System.out.println(answer[0] + "" + answer[1]); return answer; } } // System.out.println(answer[0] + "" + answer[1]); return answer; } }
아쉬운 점
- 이 문제를 해결하는데 자그마치 두시간이 걸렸다. 코딩테스트는 두시간 동안 3~4 문제를 풀어야 한다고 알고있는데 염려스럽다. 빨리 풀려고 도전해봤지만 스트레스만 쌓였다.. 자료구조 지식과 알고리즘 지식 그리고 부족한 문제풀이 경험 때문이라고 생각한다. 이를 개선하기 위해 자료구조 지식을 먼저 다져놓고 알고리즘 문제를 풀어야할 것 같다.
- 수시로 콘솔에 값을 출력해가면서 답을 찾아나갔다는 것이다. 이는 정답을 맞추기 위해 코드로 노동을 하는 기분이고, 무식한 방법으로 풀고 있다는 느낌을 준다.
- 코드가 난해하고 지저분하다…
다른 사람의 풀이
import java.util.HashSet; class Solution { public int[] solution(int n, String[] words) { int[] answer = { 0, 0 }; char chEnd = words[0].charAt(words[0].length() - 1); char chStart; System.out.print(chEnd + " "); HashSet<String> log = new HashSet<>(); log.add(words[0]); for (int i = 1; i < words.length; i++) { chStart = words[i].charAt(0); log.add(words[i]); if (chEnd != chStart || log.size() != i + 1) { System.out.print(i + 1 + "!"); answer[0] = (i % n)+1; answer[1] = (i / n) + 1; break; } chEnd = words[i].charAt(words[i].length() - 1); System.out.print(chEnd + " "); } System.out.println(); System.out.println("(" + answer[0] + ", " + answer[1] + ")"); return answer; } }
프로그래머스의 어떤 분이 이 문제를 해결한 방식이다.
- 중복된 문자열이 존재하는 경우는 HashSet 클래스를 사용해서 저장되지 않도록한다. 해당 문자열이 저장되지 않았으므로 log.size는 ≠ i + 1이 아니게 될 것이다.
- 앞 문자열의 마지막 글자는 chEnd 변수로, 현재 문자열의 첫번 째 글자는 chStart 변수로 초기화 시켜주었다.
- 만약 위 두 조건 중 하나라도 만족할 시에는
answer[0] = (i % n) + 1; answer[1] = (i / n) + 1;
로 처리해주었다. 위 로직을 출력한 예시는 아래와 같다
i = 1 i%n+1 = 2 i = 2 i%n+1 = 3 i = 3 i%n+1 = 1 i = 4 i%n+1 = 2 i = 5 i%n+1 = 3 i = 6 i%n+1 = 1 i = 7 i%n+1 = 2 i = 8 i%n+1 = 3 // i = 8일 때 tank가 두번 등장하므로 answer[0] = 3이 담긴다. //(i/n) + 1도 위와 같은 형식이지만 나누기라는 점만 다르다.
문제를 풀 때 나와 다른 점.
- HashSet으로 중복 문자열을 체크했다.
- 하나의 for문 안에 두 조건을 모두 넣어서 코드가 더 간략하다.
- 코드가 더 간략해서 가독성 + 이해하기 좋다.
- answer[0], answer[1]에 값을 넣는 방식을 나와 다른 방식의 규칙성(i%n+1 또는 i/n+1)을 사용하였다.
놀라운 점은 내가 만든 코드가 더 빠른 속도로 문제를 해결했다는 점이다. 그러므로 스스로 문제를 해결했고 좋은 결과를 낳았다는 점에서 스스로를 대견하다고 생각하면 좋을 것 같다.
'알고리즘' 카테고리의 다른 글
[DFS][부분집합] (0) 2023.02.05 [DFS][스택프레임][재귀함수] (0) 2023.02.03 [프로그래머스][lv2] 멀쩡한 사각형 Java (0) 2023.02.01 [프로그래머스][lv2] 점프와 순간이동 Java (0) 2023.01.31 [프로그래머스][lv2] 방문길이 Java (0) 2023.01.31