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);
}
}
반응형