▼ Why ?
이전 문제 [한 번 사용한 최초 문자]와 비슷한 문제이긴 하지만, 지금은 해시함수와 관련한 문제에 익숙해지는 것이 목적이기 때문에 풀어보려고 한다
▼ 한 번만 등장한 문자
문제 정보
문자열 s가 매개변수로 주어집니다. s에서 한 번만 등장하는 문자를 사전 순으로 정렬한 문자열을 return 하도록 solution 함수를 완성해보세요. 한 번만 등장하는 문자가 없을 경우 빈 문자열을 return 합니다.
코딩테스트 연습 - 한 번만 등장한 문자 | 프로그래머스 스쿨 (programmers.co.kr)
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
제한사항
- 0 < s의 길이 < 1,000
- s는 소문자로만 이루어져 있습니다.
입출력 예
어떻게 해결해야 할까?
- 일단 문자열을 생성하고 한 번만 입력한 문자들을 체크해 저장하자
- 이 경우도 문자열을 수정하는 것이기 때문에 연산 속도를 높이고 메모리를 효율적으로 사용할 수 있도록 ' StringBuilder class ' 를 이용해보자
- ' Arrays.sort() ' 메서드를 이용해 char형 배열을 사전 순으로 정렬시키자
- 정렬시킨 배열은 반환(return) 타입이 ' String ' 이기 때문에 char형 배열을 String으로 형변환해서 출력해줘야 한다
- Object class의 ' toString() ' 메서드는 문자열이 아닌 문자열의 위치인 16진수 형태의 해시코드를 반환하기 때문에, 해당 class에 미리 오버라이딩이 되어있지 않다면 문자열을 반환하도록 오버라이딩을 해주고 사용해야 한다
- 하지만, 굳이 이 문제에선 오버라이딩까지 해서 ' toString() ' 을 사용할 필요가 없기 때문에, ' String.valueOf() ' 메서드를 사용해서 문자열로 형변환을 해주도록 하자
해결 코드
import java.util.*;
class Solution {
public String solution(String s) {
HashMap<Character, Integer> map = new HashMap<>();
for(char ch : s.toCharArray()) {
map.put(ch, map.getOrDefault(ch, 0) + 1);
}
StringBuilder sb = new StringBuilder();
for(char key : map.keySet()) {
if(map.get(key) == 1)
sb.append(map.get(key));
}
String tmpStr = sb.toString;
char[] result = tmpStr.toCharArray();
Arrays.sort(result);
return String.valueOf(result);
}
}
▼ 정리
- ' String.valueOf() ' 메서드는 오버라이딩 없이 문자열로 변환해주지만, ' toString() ' 메서드는 오버라이딩을 해주지 않으면 않거나 오버라이딩이 미리 돼있는 class의 객체가 아니라면, 클래스 이름과 인스턴스의 주소를 해싱하여 변환한 값인 16진수의 해시코드를 반환한다
➜ 따라서 ' toString() ' 메서드를 사용할 것이라면 오버라이딩을 꼭 해주고 사용하자
(하지만, 알고리즘을 풀 때는 ' String.valueOf() ' 를 주로 사용할 것 같다) - StringBuilder class의 객체를 생성했을 때 초기값은 빈 문자열 ""이라는 것을 기억하자
- ' toString() ', ' String.valueOf() ' 메서드는 null 값에 따른 예외 발생 유무에서도 차이가 있다
toString() ➜ null 값을 형 변환 시 NullPointerException 예외 발생
String.valueOf() ➜ null 값을 매개변수로 받으면 "null"이라는 문자열을 반환한다