Algorithm/Java

[프로그래머스/JAVA] 숫자 문자열과 영단어 (2021 카카오 채용연계형 인턴십 문제)

dbfl9911 2024. 10. 29. 21:55
반응형

https://school.programmers.co.kr/learn/courses/30/lessons/81301

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

📌 문제 요약 

  • 문자열 s에서 숫자가 포함된 부분은 그대로 두고, 영단어로 표현된 숫자를 실제 숫자로 변환해야 한다.
  • 예: "one4seveneight" → 1478, "23four5six7" → 234567


[ 오답 노트 ]


❌ 기존 오답 코드

해시맵을 사용해 접근하려 했지만 틀렸다 ㅜ

import java.util.*;

class Solution {
    public int solution(String s) {
        String answer = "";
        
        HashMap<Integer,String> hm = new HashMap<>();
        hm.put(0, "zero"); hm.put(1, "one"); hm.put(2, "two");
        hm.put(3, "three"); hm.put(4, "four"); hm.put(5, "five");
        hm.put(6, "six"); hm.put(7, "seven"); hm.put(8, "eight");
        hm.put(9, "nine");
        
        // 한글자씩 점검??
        for(int i = 0; i < s.length(); i++) {
            for(Map.Entry<Integer, String> entry : hm.entrySet()) {
                // 숫자라면?
                if(s.charAt(i) == entry.getKey()) {
                    answer += s.charAt(i);
                }
                // 문자라면? 
                if(s.contains(entry.getValue())) {
                    answer += entry.getKey();
                }
            }
        }
        
        return Integer.parseInt(answer);
    }
}


📌 기존 코드의 문제점

1. char와 Integer의 비교 

if (s.charAt(i) == entry.getKey())

s.charAt()는 char 타입이고 entry.getKey()는 Integer 타입이므로 타입이 달라 항상 false가 반환된다

 

 

2. s.contains(entry.getValue())의 비효율성

if (s.contains(entry.getValue()))

 

  • s.contains()는 문자열에 특정 값이 포함되어 있는지만 확인한다
  • 하지만 변환 과정에서 이미 처리된 문자열 부분을 다시 확인하거나, 처리 순서를 보장하지 못한다

 

3. answer에 잘못된 값이 누적

 

  • 변환된 숫자를 제대로 관리하지 않아 중복되거나 엉뚱한 값이 누적될 가능성이 크다
  • 처리한 부분을 문자열 s에서 제거하거나 대체하지 않으므로 변환이 정확히 이루어지지 않는다

 

4. 중첩된 for 루프 사용

 

  • 문자열의 각 문자마다 모든 숫자와 영단어를 반복적으로 비교하므로 매우 비효율적이다
  • 입력 길이가 길어지면 성능 문제가 발생할 가능성이 크다

 



[ 정답 코드 & 올바른 풀이 ]


📌 올바른 풀이

m1) 해시맵으로 푸는 방법

문자열을 한 글자씩 탐색하며 영단어를 누적(temp)하여 숫자로 변환한다

 

 

m2) 해시맵 사용하지 않고 더 간단한 코드로 구현 

  • 문자열에서 숫자 영단어를 숫자로 순서대로 대체한다.
  • 문자열 치환을 반복적으로 수행하여 영단어를 모두 변환

 

 



📌 정답 코드

m1) 해시맵으로 구현

import java.util.*;

// m1) 해시맵 사용 방법
class Solution {
    public int solution(String s) {
        // String은 불변이므로 StringBuilder를 사용하는게 성능 측면에서 유리
        StringBuilder answer = new StringBuilder();
        StringBuilder temp = new StringBuilder(); // 영단어를 누적할 문자열

        HashMap<String, Integer> hm = new HashMap<>();
        hm.put("zero", 0); hm.put("one", 1); hm.put("two", 2);
        hm.put("three", 3); hm.put("four", 4); hm.put("five", 5);
        hm.put("six", 6); hm.put("seven", 7); hm.put("eight", 8);
        hm.put("nine", 9);

        // 한글자씩 점검
        for(int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            // 1.숫자인 경우
            // 문자가 숫자인지 판단하는 함수인 Character.isDigit()를 사용
            if(Character.isDigit(c)) {
                answer.append(c);
                // 2.문자인 경우
            }else {
                temp.append(c); // z -> ze -> zer -> zero

                // temp가 영단어와 매핑되면 숫자로 변환
                // (temp를 toString활용해서 문자열로 변환)
                if(hm.containsKey(temp.toString())) {
                    answer.append(hm.get(temp.toString()));
                    temp.setLength(0); // temp 초기화
                }
            }
        }

        return Integer.parseInt(answer.toString());
    }
}

 

 

m2) 해시맵 사용하지 않고 배열로 구현 

class Solution {
   public int solution(String s) {
       // 영단어 배열 정의
       String[] words = { "zero", "one", "two", "three", "four",
               "five", "six", "seven", "eight", "nine"};
       // 문자열에서 영단어를 순차적으로 숫자로 변환
       for(int i = 0; i < words.length; i++) {
           // 문자열 .replace() 활용해 문자열 포함된 기존 문자를 바꿀 문자로 변환
           s = s.replace(words[i], String.valueOf(i));
       }

       return Integer.parseInt(s);
   }
}
반응형