ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [프로그래머스/JAVA] 숫자 문자열과 영단어 (2021 카카오 채용연계형 인턴십 문제)
    Algorithm/Java 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);
       }
    }
    반응형
Designed by Tistory.