본문 바로가기
알고리즘/문제풀이

2018 카카오 블라인드 코딩테스트 3차(프로그래머스, 모든 문제, Java)

by 모스키토끼 2019. 11. 23.

1. N진수 게임

문제 링크: https://programmers.co.kr/learn/courses/30/lessons/17687

 

코딩테스트 연습 - [3차] n진수 게임 | 프로그래머스

N진수 게임 튜브가 활동하는 코딩 동아리에서는 전통적으로 해오는 게임이 있다. 이 게임은 여러 사람이 둥글게 앉아서 숫자를 하나씩 차례대로 말하는 게임인데, 규칙은 다음과 같다. 숫자를 0부터 시작해서 차례대로 말한다. 첫 번째 사람은 0, 두 번째 사람은 1, … 열 번째 사람은 9를 말한다. 10 이상의 숫자부터는 한 자리씩 끊어서 말한다. 즉 열한 번째 사람은 10의 첫 자리인 1, 열두 번째 사람은 둘째 자리인 0을 말한다. 이렇게 게임을 진행할

programmers.co.kr

알고리즘 설명:

10진수를 주어진 진수로 바꾼 뒤 한 글자씩 list에 넣어 알려줘야 하는 개수만큼 반복문을 돌리면 되는 문제이다.

  • 시작은 무조건 0 - answerlist에 넣고 시작
  • list를 두 개 사용한 이유는 진수로 변환할 때 나눈 나머지를 차례대로 list에 넣어서 결과를 보면 list에 값이 반대로 들어가 있다. 그래서 십진수를 진수로 나눈 나머지들을 list에 넣은 뒤 reverse를 해주어야 진수 변환이 정상적으로 들어간다.
  • 십진수의 변환이 완료되면 answerlist에 그대로 넣어 누적시켜준다.
  • answerlist의 크기가 m(게임에 참가한 인원)* t(구해야 할 답의 개수) 보다 커지기 전까지 반복
  • 튜브의 순서 인덱스는 p-1 이므로 탐색 시작 인덱스를 p-1로 하고 인덱스를 m씩 늘려가며 답을 탐색
  • 혹시나 하는 생각에 찾는 값의 개수가 t(구해야 할 답의 개수)와 같아졌을 때 탐색 반복문을 break 한다.

코드(Java)

package test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class NumberGame {
	public static String solution(int n, int t, int m, int p) {
		String answer = "";
		List<Character> list = new ArrayList<>();
		List<Character> listanswer = new ArrayList<>();
		int i=1;
		listanswer.add('0');
		while(listanswer.size()<(m*t)){
			int num = i;
			while (num != 0) {
				int insert = num % n;
				char listadd;
				
				if (insert >= 10) {
					listadd = (char) ('A' + (insert % 10));

				} else {
					listadd = (char) ('0' + insert);
				}
				list.add(listadd);
				num = num / n;
			}
			Collections.reverse(list);
			i++;
			listanswer.addAll(list);
			list.clear();
		}
	
		int index = p-1;
		int count=0;
		while(index<listanswer.size()) {
			answer += listanswer.get(index).toString();
			index+=m;
			count++;
			if(count==t)break;
			
		}
		return answer;
	}

	public static void main(String[] args) {
		System.out.println(solution(2, 4, 2, 1));
	}

}

2. 압축

문제 링크: https://programmers.co.kr/learn/courses/30/lessons/17684

 

코딩테스트 연습 - [3차] 압축 | 프로그래머스

TOBEORNOTTOBEORTOBEORNOT [20, 15, 2, 5, 15, 18, 14, 15, 20, 27, 29, 31, 36, 30, 32, 34]

programmers.co.kr

알고리즘 설명:

Hashmap에 추가 되는 단어들을 저장하면서 정답을 누적해가면 쉽게 구할 수 있다.

  • 문제에서 주어진 것처럼 알파벳 26자를 Hashmap에 저장하고 시작(HashMap이 사전 역할)
  • 주어진 문자열의 인덱스에 하나씩 접근
    • Hashmap에 존재하지 않은 경우가 나올 때까지 접근한 인덱스에서 길이를 늘려가면서 탐색
    • print에는 출력해야 될 값 즉 Hashmap에 들어있는 값들을 계속 경신해준다.
  • Hashmap에 존재하지 않은 경우가 나오면 그 문자열을 Hashmap저장
  • 탐색한 만큼 탐색 인덱스를 옮겨준다.
  • list에 있는 값들을 모두 더하면 answer!

코드(Java)

package test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Compression {
	  public static int[] solution(String msg) {
	      Map<String,Integer> map = new HashMap<>();
	      List<Integer>list = new ArrayList<>();
	      int w=26;
	      for(int i=0;i<26;i++) {
	    	  String key = Character.toString((char) ('A'+i));
	    	  map.put(key, i+1);
	      }
	      
	      char[] msgarr = msg.toCharArray();
	      for(int i=0;i<msgarr.length;) {
	    	  String temp = Character.toString(msgarr[i]);
	    	  int searchIndex = 0;
	    	  int print =0;
	    	  while(map.containsKey(temp)){
	    		  print = map.get(temp);
	    		  searchIndex++;
	    		  if((i+searchIndex)>(msgarr.length-1))break;
	    		  temp+=Character.toString(msgarr[i+searchIndex]);
	    	  }
	    	  list.add(print);
	    	  map.put(temp, ++w);
	    	  i+=searchIndex;
	      }
	      int[] answer = new int[list.size()];
	      for(int i=0;i<list.size();i++) {
	    	  answer[i] = list.get(i);
	      }
	      return answer;
	  }

	public static void main(String[] args) {
		int[] answer= solution("KAKAO");
		for(int i=0;i<answer.length;i++) {
			System.out.println(answer[i]);
		}
		
	}

}

3. 파일명 정렬

문제 링크: https://programmers.co.kr/learn/courses/30/lessons/17686

 

코딩테스트 연습 - [3차] 파일명 정렬 | 프로그래머스

파일명 정렬 세 차례의 코딩 테스트와 두 차례의 면접이라는 기나긴 블라인드 공채를 무사히 통과해 카카오에 입사한 무지는 파일 저장소 서버 관리를 맡게 되었다. 저장소 서버에는 프로그램의 과거 버전을 모두 담고 있어, 이름 순으로 정렬된 파일 목록은 보기가 불편했다. 파일을 이름 순으로 정렬하면 나중에 만들어진 ver-10.zip이 ver-9.zip보다 먼저 표시되기 때문이다. 버전 번호 외에도 숫자가 포함된 파일 목록은 여러 면에서 관리하기 불편했다. 예

programmers.co.kr

알고리즘 설명:

문자열을 Head, Number, Tail로 분리하는 전처리 후 Sorting을 하면 해결

  • 숫자가 나오기 전까지 Head, 숫자가 Number, 나머지 Tail로 split 해준다.
  • Arrays.sorting, Comparator를 사용하여 Head 순으로 정렬하되 Head가 같은 경우 Number로 정렬을 한다.
  • 정렬된 순서대로 출력하면 끝

막혔던 지점:

해설을 읽어보니 안정 정렬을 사용해야지만 문제가 풀린다던데 다행히 자바에서 제공해주는 메서드인 Arrays.sort는 안정 정렬인 삽입 정렬과 병합 정렬을 사용하여서 문제가 풀렸다.

또 문제의 조건인 Number의 최대 길이가 5 자라는 조건을 적용을 하지 않았더니 일부 테스트 케이스가 틀렸다고 나왔다. (정말 무섭다 무서워...)

코드(Java)

package test;

import java.util.Arrays;
import java.util.Comparator;

public class FilenameSorting {
	public static String[] solution(String[] files) {
		String[] answer = new String[files.length];
		String[][] headNumTail = new String[files.length][3];

		for (int i = 0; i < files.length; i++) {

			headNumTail[i][0] = files[i];
			headNumTail[i][1] = files[i].split("[0-9]")[0];
			files[i]=files[i].replace(headNumTail[i][1], "");
			
			headNumTail[i][1] = headNumTail[i][1].toUpperCase();
			char[] arr = files[i].toCharArray();
			
			headNumTail[i][2] = "";
            for(char c : arr) {
                if(Character.isDigit(c) && headNumTail[i][2].length() < 5) {
                	headNumTail[i][2] += c;
                } else {
                    break;
                }
            }
		}

		Arrays.sort(headNumTail, new Comparator<String[]>() {
			@Override
			public int compare(String[] o1, String[] o2) {

				return o1[1].equals(o2[1]) ? Integer.parseInt(o1[2]) - Integer.parseInt(o2[2]) : o1[1].compareTo(o2[1]);
			}
		});

		for (int i = 0; i < files.length; i++) {
			answer[i] = headNumTail[i][0];
		}
		return answer;
	}
	
	public static void main(String[] args) {
		
		  String[] answer = solution( new String[] { "img12.png", "img10.png",
		  "img02.png", "img1.png", "IMG01.GIF", "img2.JPG" });
		  
		  for (int i = 0; i < answer.length; i++) { System.out.println(answer[i]); }
		 
		answer = solution(
				new String[] { "F-5 Freedom Fighter", "B-50 Superfortress", "A-10 Thunderbolt II", "F-14 Tomcat" });
		for (int i = 0; i < answer.length; i++) {
			System.out.println(answer[i]);
		}
	}

}

4. 방금 그 곡

문제 링크: https://programmers.co.kr/learn/courses/30/lessons/17683

 

코딩테스트 연습 - [3차] 방금그곡 | 프로그래머스

방금그곡 라디오를 자주 듣는 네오는 라디오에서 방금 나왔던 음악이 무슨 음악인지 궁금해질 때가 많다. 그럴 때 네오는 다음 포털의 '방금그곡' 서비스를 이용하곤 한다. 방금그곡에서는 TV, 라디오 등에서 나온 음악에 관해 제목 등의 정보를 제공하는 서비스이다. 네오는 자신이 기억한 멜로디를 가지고 방금그곡을 이용해 음악을 찾는다. 그런데 라디오 방송에서는 한 음악을 반복해서 재생할 때도 있어서 네오가 기억하고 있는 멜로디는 음악 끝부분과 처음 부분이 이어

programmers.co.kr

알고리즘 설명:

  • InFo라는 클래스를 만들어서 재생된 곡 정보들의 이름과 멜로디를 관리
  • 반올림한 맬로디는 소문자로 바꾸어 하나의 문자로 비교 가능하게 전처리
  • 방송된 시간만큼 맬로디를 반복시킨 문자열에 네오의 멜로디가 들어 있는 경우 list에 Info 객체로 add 시킨다.
  • list를 info 객체의 music 길이 즉 방송 길이 순으로 정렬을 한 면 인덱스 0 값이 정답

코드(Java)

package test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class RecentSong {

	public static String solution(String m, String[] musicinfos) {
		m = m.replace("C#", "c").replace("D#", "d").replace("F#", "f").replace("G#", "g").replace("A#", "a");
		List<Info> matchList = new ArrayList<>();

		for (int i = 0; i < musicinfos.length; i++) {

			String[] sp = musicinfos[i].split(",");
			String[] startTime = sp[0].split(":");
			String[] endTime = sp[1].split(":");
			int end = (Integer.parseInt(endTime[0]) * 60 + Integer.parseInt(endTime[1]));
			int start = Integer.parseInt(startTime[0]) * 60 + Integer.parseInt(startTime[1]);
			int time = end - start;
			String music = "";
			sp[3] = sp[3].replace("C#", "c").replace("D#", "d").replace("F#", "f").replace("G#", "g").replace("A#",
					"a");

			int j = 0;
	        for(int k = 0; k < time ; k++) {
	            j = k % sp[3].length();
	            music += sp[3].charAt(j);
	        }

			if (music.contains(m)) {
				matchList.add(new Info(sp[2], music));
			}
		}
		Collections.sort(matchList, new Comparator<Info>() {

			@Override
			public int compare(Info o1, Info o2) {
				return o2.music.length() - o1.music.length();
			}
		});

		return matchList.size() > 0 ? matchList.get(0).name : "(None)";
	}

	public static class Info {
		String name;
		String music;

		public Info(String name, String music) {
			this.name = name;
			this.music = music;
		}
	}

	public static void main(String[] args) {
		solution("CC#BCC#BCC#BCC#B", new String[] { "03:00,03:30,FOO,CC#B", "04:00,04:08,BAR,CC#BCC#BCC#B" });
	}

}

 


5. 자동완성

문제 링크: https://programmers.co.kr/learn/courses/30/lessons/17685

 

코딩테스트 연습 - [3차] 자동완성 | 프로그래머스

자동완성 포털 다음에서 검색어 자동완성 기능을 넣고 싶은 라이언은 한 번 입력된 문자열을 학습해서 다음 입력 때 활용하고 싶어 졌다. 예를 들어, go 가 한 번 입력되었다면, 다음 사용자는 g 만 입력해도 go를 추천해주므로 o를 입력할 필요가 없어진다! 단, 학습에 사용된 단어들 중 앞부분이 같은 경우에는 어쩔 수 없이 다른 문자가 나올 때까지 입력을 해야 한다. 효과가 얼마나 좋을지 알고 싶은 라이언은 학습된 단어들을 찾을 때 몇 글자를 입력해야 하

programmers.co.kr

알고리즘 설명:

사전 순으로 정렬한 뒤 앞 뒤 값들만 비교하면 풀리는 문제

  • Comparator를 사용하여 배열을 정렬한다.
    • 비교 문자열을 문자 배열로 바꾸고 한 문자씩 비교하면서 다른 경우가 존재하면 그 글자를 기준으로 sort
    • 비교 문자열 중 하나가 다른 하나에 포함되는 경우라면 길이가 짧은 순으로 sort
  • 문자열 배열의 처음 index(0)와 끝 index(words.length -1)는 각각 뒤 index와 앞 index만 비교, 나머지 index들은 앞 뒤 index 둘 다 비교
  • 앞 뒤 index들과 앞에서부터 다른 문자가 나올 때까지 같은 문자의 개수를 카운트한다.
  • 앞 뒤 중 더 카운트 개수가 큰 값을 answer에 누적시켜준다.
  • 앞 index가 현재 index에 포함되는 경우라면 카운트 개수가 1개 덜 나오기 때문에 그 경우에 카운트 +1

 

막힌 지점:

해설에서는 Trie 알고리즘으로 문제를 풀면 된다고 나와있지만 그냥 그대로 Trie를 사용하면 정답 100%가 나오지 않는다. 예상으로는 깊이 설정을 해줘야 하는 것 같은데 확실히 모르겠다...

 

코드(Java)

package test;

import java.util.Arrays;
import java.util.Comparator;

public class AutomaticComplete {

	public static int solution(String[] words) {
		int answer = 0;
		Arrays.sort(words, new Comparator<String>() {

			@Override
			public int compare(String beforeWord, String aftereWord) {
				char[] before = beforeWord.toCharArray();
				char[] after = aftereWord.toCharArray();

				for (int i = 0; i < before.length && i < after.length; i++) {
					if (before[i] != after[i])
						return before[i] - after[i];
				}

				return before.length > after.length ? 1 : -1;
			}

		});

		for (int i = 0; i < words.length; i++) {
			char[] word = words[i].toCharArray();
			int countBefore = 0;
			int countAfter = 0;

			if (i != 0) {
				char[] before = words[i - 1].toCharArray();
				countBefore = 0;
				for (int j = 0; j < word.length && j < before.length; j++) {
					countBefore++;
					if (word[j] != before[j])
						break;

					if (j == before.length - 1)
						countBefore++;
				}
			}

			if (i != words.length - 1) {
				char[] next = words[i + 1].toCharArray();
				countAfter = 0;
				for (int j = 0; j < word.length && j < next.length; j++) {
					countAfter++;
					if (word[j] != next[j])
						break;
				}
			}

			if (countBefore > countAfter)
				answer += countBefore;
			else
				answer += countAfter;


		}

		return answer;
	}

	public static void main(String[] args) {

		System.out.println(solution(new String[] { "go", "gone", "guild" }));

		System.out.println(solution(new String[] { "abc", "def", "ghi", "jklm" }));
		System.out.println(solution(new String[] { "word", "war", "warrior", "world" }));

	}

}

댓글