본문 바로가기

알고리즘/프로그래머스

[JAVA] 프로그래머스 - 영어 끝말잇기

문제내용

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

 

코딩테스트 연습 - 영어 끝말잇기

3 ["tank", "kick", "know", "wheel", "land", "dream", "mother", "robot", "tank"] [3,3] 5 ["hello", "observe", "effect", "take", "either", "recognize", "encourage", "ensure", "establish", "hang", "gather", "refer", "reference", "estimate", "executive"] [0,0]

programmers.co.kr

1부터 n까지 번호가 붙어있는 n명의 사람이 영어 끝말잇기를 하고 있습니다. 영어 끝말잇기는 다음과 같은 규칙으로 진행됩니다.

  1. 1번부터 번호 순서대로 한 사람씩 차례대로 단어를 말합니다.
  2. 마지막 사람이 단어를 말한 다음에는 다시 1번부터 시작합니다.
  3. 앞사람이 말한 단어의 마지막 문자로 시작하는 단어를 말해야 합니다.
  4. 이전에 등장했던 단어는 사용할 수 없습니다.
  5. 한 글자인 단어는 인정되지 않습니다.

다음은 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 해주세요.

문제 풀이

문제에서 주어진 조건에 맞게 끝말잇기를 구현해내기만 하면 되는문제다. 특별한 알고리즘은 필요없다.

 

조건

1. 끝말잇기니까 이전 단어의 끝글자와 현재 말하는 단어의 맨앞글자는 같아야함.

2. 중복되는 단어가 나오면 멈춤.

 

로직

1. 끝에 글자를 비교하기 위해 스택사용해서 마지막에 들어온 단어의 끝글자가 현재 말하는 단어의 맨앞글자가 같은지 봄.

2. 단어가 나올때 마다 해쉬셋을 이용해 중복확인함.

3. 순서를 나타낼 변수 idx와 idx번째 사람이 몇번째 차례인지 나타낼 seq 배열을 이용해 순서와 몇번째인지 기억.

4. 모든 단어 순회가 기본이고 만약 1,2 번에서 걸리게되면 그때 반복문 멈추고 idx와 seq[idx]을 반환.

5. 만약 모든 단어가 정상정으로 이뤄지면 0,0을 반환.

 


코드

package org.test.kakao.lv2;

import java.util.HashSet;
import java.util.Stack;

public class Solution {
    public int[] solution(int n, String[] words) {
        int idx = 0;//몇번째 사람인지 나타낼 변수
        int[] seq = new int[n+1];//idx번째 사람이 몇번째 차례로 말했는지 저장해줄 배열
        boolean flag = false;//중복 or 끝말잇기가 아니면 true로 바뀔 변수
        HashSet<String> set = new HashSet<>(); // 중복확인
        Stack<String> stack = new Stack<>(); // 끝말잇기
        
        //초기값 셋업
        set.add(words[0]);
        stack.add(words[0]);
        seq[++idx]++;// idx먼저 증가시키고 seq[idx]증가
        
        //모든단어 순회, 첫번째 단어는 위에서 초기값으로 셋업 했기때문에 1부터 시작. 
        for(int i=1; i<words.length; i++) {
        	String cur = words[i];//현재 단어
        	if(idx==n) idx=0;//만약 n번째 사람까지 왔으면 idx 초기화
        	if(set.contains(cur)) {//중복확인
        		seq[++idx]++;
        		flag = true;
        		break;
        	}
        	if(stack.peek().charAt(stack.peek().length()-1)!=cur.charAt(0)) {//끝말잇기인지 확인
        		seq[++idx]++;
        		flag = true;
        		break;
        	}
        	
        	//정상적인 끝말잇기일때
        	set.add(words[i]);
        	stack.add(words[i]);
        	seq[++idx]++;
        }
        
        int[] answer = new int[2];
        if(!flag) {
        	answer[0]=0;
        	answer[1]=0;
        }
        else {
        	answer[0]=idx;
        	answer[1]=seq[idx];
        }
        return answer;
    }
}

마치며

특별히 어려운게 없는 문제고, 만약 못 풀엇으면 문제를 좀더 풀어볼 필요가 있다.