프로그래머스/Lv. 0(코딩테스트 입문)

[프로그래머스 코딩테스트] 모스부호 (1)(Java)

Sigfriede 2023. 6. 4. 01:00

  문제 설명

  머쓱이는 친구에게 모스부호를 이용한 편지를 받았습니다. 그냥은 읽을 수 없어 이를 해독하는 프로그램을 만들려고 합니다. 문자열 letter가 매개변수로 주어질 때, letter를 영어 소문자로 바꾼 문자열을 return 하도록 solution 함수를 완성해보세요.

 

  제한사항

  • 1 <= letter의 길이 <= 1,000
  • return 값은 소문자입니다.
  • letter의 모스부호는 공백으로 나누어져 있습니다.
  • letter에 공백은 연속으로 두 개 이상 존재하지 않습니다.
  • 해독할 수 없는 편지는 주어지지 않습니다.
  • 편지의 시작과 끝에는 공백이 없습니다.

 

  입출력 예

letter result
".... . .-.. .-.. ---" "hello"
".--. -.-- - .... --- -." "python"
import java.lang.StringBuilder;
class Solution {
    public String solution(String letter) {
        String[] morse = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."};
        String[] alp = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"};
        
        StringBuilder sb = new StringBuilder();
        for (String s: letter.split(" ")) {
            for (int i = 0; i < morse.length; i++) {
                if (s.equals(morse[i])) {
                    sb.append(alp[i]);
                }
            }
        }
        String answer = sb.toString();
        return answer;
    }
}

  문자열 배열 morse와 alp 배열을 생성합니다. 각각 문제에서 주어진 대로 할당했습니다.

  StringBuilder를 생성합니다.

  for-each문에서 split 메소드를 이용하여 letter를 공백으로 구분합니다. 문자열 s는 분리한 문자열를 하나씩 받습니다.

  안쪽 for문에서 i는 morse의 길이만큼 순회합니다. equal 메소드를 이용하여 문자열 s가 morse의 i번째 원소와 같은지 확인합니다. 만약 같다면 append 메소드를 이용하여 alp의 i번째 원소를 StringBuilder에 추가합니다. morse와 alp는 동일한 i에 대해 동일한 문자를 의미하기 때문에 i 값을 공유합니다.

  반환하기 전 toString 메소드를 이용하여 StringBuilder가 메모리 주소가 아닌 올바른 문자열을 반환할 수 있도록 합니다.

import java.lang.StringBuilder;
import java.util.HashMap;
class Solution {
    public String solution(String letter) {
        String[] morse = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."};
        HashMap<String, Character> map = new HashMap<>();
        for (int i = 0; i < morse.length; i++) {
            map.put(morse[i], (char)(97 + i));
        }
        
        StringBuilder sb = new StringBuilder();
        String[] str = letter.split(" ");
        for (String s: str) {
            sb.append(map.get(s));
        }
        String answer = sb.toString();
        return answer;
    }
}

  이 문제는 HashMap을 이용하여 푼다면 더 빠른 연산이 가능하지 않을까 싶어 풀어보았습니다. 풀이 방식은 앞의 과정과 유사합니다.

  HashMap을 생성합니다. 제네릭 타입으로는 String과 Character가 들어갑니다.

  for문이 morse의 길이만큼 순회합니다. put 메소드를 이용하여  key 값에는 모스 부호를, value 값에는 모스 부호에 대응하는 알파벳 문자가 들어갈 것입니다. 97은 아스키 코드를 이용한 것입니다. 'a'와 동일합니다.

  StringBuilder를 생성합니다. split 메소드를 이용하여 letter를 공백으로 구분합니다. 이를 str에 할당합니다.

  for-each문이 str을 s로 받습니다. get 메소드를 이용하여 map에서 s와 동일한 key에서 value를 가져옵니다. append 메소드를 이용하여 가져온 value를 StringBuilder에 추가합니다.

  마찬가지로 반환하기 전 toString 메소드를 이용하여 올바른 값을 반환할 수 있도록 합니다.

  문자의 개수는 한정되어 있고 letter의 길이 역시 제한이 천 자 정도로 적은 편이지만, 만약 문자열의 길이가 더 길어진다면 두 식의 연산시간의 격차는 점점 더 벌어질 것이라고 예상했습니다. 하지만 결과는 달랐습니다.

왼쪽은 중첩 for문, 오른쪽은 해시를 이용한 풀이

  for문이 묘하게 더 빨랐습니다. 정확한 이유는 모르겠으나 해시를 이용한 풀이는 해시 함수를 거치는 과정에서 느려진 것이 아닐까 추측합니다.