알고리즘

[004] 숫자 문자열과 영단어

돈기법 2022. 4. 4. 00:12

https://programmers.co.kr/learn/courses/30/lessons/81301?language=java 

 

코딩테스트 연습 - 숫자 문자열과 영단어

네오와 프로도가 숫자놀이를 하고 있습니다. 네오가 프로도에게 숫자를 건넬 때 일부 자릿수를 영단어로 바꾼 카드를 건네주면 프로도는 원래 숫자를 찾는 게임입니다. 다음은 숫자의 일부 자

programmers.co.kr

 

[답]

import java.util.HashMap;
import java.util.Map.Entry;

public class Solution {

    public int solution(String s) {
        int answer = 0;
        
        HashMap<String, Integer> hm = new HashMap<String, Integer>();
        
        String arr[] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};

        int i = 0;
        
        //해시맵에 저장
        for (String string : arr) {
        	hm.put(string, i);
        	i++;
	}
        
        //문자열의 영어(key) 부분을 숫자(value)로 치환
        for (Entry<String, Integer> entry : hm.entrySet()) {
        	s = s.replace(entry.getKey(), Integer.toString(entry.getValue()));
	}
        
        //치환한 문자열을 int값으로 변환
        answer = Integer.parseInt(s);
        
        return answer;
    }  
}

 

[풀이]

해시맵에 key에 영단어와 value에 해당 영단어의 값을 저장한 후, replace() 메서드를 사용해서 치환해주었다.

(이렇게까지 하지 않았어도 됐는데 이유는 나중에 서술...)

 

replace("a", "b") -> 문자열에서 a를 찾아 b로 치환시킨다.

 

replace()와 비슷한 메서드로 replaceAll()도 있는데 둘은 약간의 차이가 있다.

String  str = "Hello World.";
str = str.replace(".", "^^");
System.out.println(str); // 결과 : Hello World^^

String str2 = "Hello World.";
str2 = str2.replaceAll(".", "^^");
System.out.println(str2); // 결과 : ^^^^^^^^^^^^^^^^^^^^^^^^

replace()는 "."을 문자로 인식했지만, replaceAll()은 "."을 정규식으로 인식해서 모든 문자를 "^^"로 바꿔버린다.

 

 

 

여기서 잠깐 정규식 간단 사용법


정규표현식

[a-z] : a~z 사이의 문자(소문자)를 찾음.

[A-Z] : A~Z 사이의 문자(대문자)를 찾음.

[0-9] : 0~9 사이의 숫자를 찾음.

[abc] : a, b, c 중 하나를 찾음.

[^abc] : a, b, c를 제외한 문자를 찾음.

DOT(.) : 모든 문자열

[\\s] : 띄어쓰기

[^\uAC00-\uD7A30-9a-zA-Z] : 한글, 숫자, 영문, 띄어쓰기 빼고 모든 특수문자 제거

 

ex)

// ^ : 문자열의 시작
// $ : 문자열의 종료

s.replaceAll("[-]", "")	// 특정문자 제거 (-)
s.replaceAll("[^0-9]", "");	// 숫자 빼고 모든 문자
s.replaceAll("[\\s]", "");	// 띄어쓰기
s.replaceAll("[^\uAC00-\uD7A30-9a-zA-Z]", "");	// 모든 특수문자 제거

 

 

문자열로 치환하기 때문에 value값을 Integer.toString()을 사용해 문자로 변경해주었다.

return값은 int이기 때문에 Integer.parseInt()를 사용해 숫자로 변경해준 후 리턴해주었다.

 

 

해시맵으로 끙끙거리며 열심히 풀다가

같이 문제를 풀던 친구에게 코드를 보여줬더니 굳이 해시맵에 따로 저장하지 않고도 풀 수 있다는 말을 들었다.

배열만으로도 풀 수 있다길래 어떻게?.. 그거 어떻게 하는건데 하면서 분노를 표출하자마자 떠올랐다 인덱스(index)...

 

String arr[] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};

 

이런 구조에선 어차피 arr[0] = "zero", arr[1] = "one" ... 이기 때문에 key-value로 지정하지 않고도 가능했다.

 

분노를 연료 삼아 다시 풀었다.

import java.util.Arrays;

public int solution(String s) {
    int answer = 0;
    
    String arr[] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
    
    //자바에서는 배열에 indexOf()를 지원하지 않고, ArrayList 자료구조에서만 지원하므로
    //Arrays.asList()를 통해 변환시켜 인덱스를 구해야 함.
    for (String string : arr) {
	s = s.replace(string, Integer.toString(Arrays.asList(arr).indexOf(string)));
    }
    
    answer = Integer.parseInt(s);
    
    return answer;
}

찾아보니 자바에서는 배열에 indexOf()를 지원하지 않고 ArrayList에서만 지원하기 때문에 asList()를 통해 변환해줘야 했다.

 

indexOf() : 특정 문자나 문자열이 앞에서부터 처음 발견되는 인덱스를 반환. 만약 찾지 못했을 경우 -1 반환.

lastIndexOf() : 뒤에서부터 처음 발견되는 인덱스를 반환. 만약 찾지 못했을 경우 -1 반환.

 

asList()를 사용해 List 객체를 만들 때 새로운 배열 객체를 만드는 것이 아니라 원본 배열의 주소값을 가져온다.

따라서 asList()를 사용한 객체를 수정하면 원본 배열도 함께 바뀌게 되고,

원본 배열을 수정하면 생성한 List 객체 내용도 바뀌게 된다.

Arrays.asList()는 고정 길이의 List를 리턴하기 때문에 새로운 값을 추가할 경우 Exception을 발생시킨다.

 

 

지금보니 List<String> list = Arrays.asList(arr); 로 list를 생성해놓고 list.indexOf(string) 으로 썼으면 가독성이 더 좋았을 것 같다.

 

 

 

- 참고 글

https://coding-factory.tistory.com/128

 

[Java] 문자열 치환(Replace) 사용법 & 예제

String변수나 배열 같은 곳에 많은 양의 데이터들이 들어가 있을 경우 자신이 바꾸고자 하는 값만 골라서 바꾸기란 쉽지 않습니다. 이럴 때 유용하게 쓰일 수 있는 함수가 바로 Replace함수입니다.

coding-factory.tistory.com

 

https://hianna.tistory.com/551

 

[Java] 배열을 List로, List를 배열로 변환하기

배열을 List로 Arrays.asList() new ArrayList<>(Arrays.asList()) Collectors.toList() ArrayList를 배열로 toArray() - java.util.List 배열을 List로 1. Arrays.asList() 코드  import java.util.Arrays; impo..

hianna.tistory.com

https://earth-ing.tistory.com/38?category=974768 

 

[Java] replaceAll() 특수문자 제거, 숫자빼고, 문자빼고 총 정리

replaceAll은 쓸때마다 참 헷갈리는 것같다.. ​ 기본적으로 알아야할 것은 str.replaceAll("[{바꾸고싶은 문자의 정규식}]", "{치환할 문자}"); 이렇게 사용하는데 정규식이 아주 헷갈리고 쓰기 어려울 때

earth-ing.tistory.com