튜플
문제 링크 : https://school.programmers.co.kr/learn/courses/30/lessons/64065
접근 방식
- 주어진 문자열은, 배열안에 배열이 있는 형식으로, 2차원 배열과 비슷한 형태를 띄고 있다.
- 각 배열의 길이가 짧은 순부터 큰 순으로 값을 비교하면, 원본 튜플을 찾을 수 있다.
- 주어진 문자열의 배열을 순수 숫자만 남겨둔다.
- 여기서 배열의 크기로 비교하고 정렬할 수 있도록, TreeMap을 이용해 자동 정렬될 수 있도록 한다.
- 이후 TreeMap의 밸류를 forEach로 돌면서 중복 숫자는 제거하고 List에 넣는다.
- List를 배열로 변환해서 리턴한다.
잘못된 접근
import java.util.*;
class Solution {
public int[] solution(String s) {
List<String> answer = new ArrayList<>();
s = s.substring(2, s.length()-2).replace("},{", " ");
Map<Integer, String> map = new TreeMap<>();
String tmp[] = s.split(" ");
for(String t:tmp){
t = t.replace(",","");
map.put(t.length(), t);
}
for(String string:map.values()){
String x = string;
for(int i=0; i<answer.size(); i++){
x = x.replace(answer.get(i), "");
}
answer.add(x);
}
return answer.stream().mapToInt(a->Integer.parseInt(a)).toArray();
}
}
그 결과 만들어진 코드이다.
위 코드는, 주어진 테스트 케이스와 일부 정확성 테스트를 통과했다.
하지만 일부 테스트에서는 런타임 에러를 발생했다.
도무지 이유를 모르겠어서, 질문하기를 통해 엣지 테스트 케이스를 발견하게 되었다.
"{1}, {11, 1}, {11, 111, 1}"
위 문자열이 주어진다면, 현재 코드에서는 1이 들어있는 모든 것을 대체한다.
따라서, 첫 1은 추가되지만, 이후에는 1이 모두 공백으로 치환되어 공백이 List
이후에는, Integer.parseInt(a) 에서 공백이 int로 변환되지 못하기 때문에, 런타임 오류가 발생하게 된다.
따라서, 중복 여부를 판단하는 로직을 Set 자료구조를 사용하는 것으로 변경하여,
Set에 없는 경우에 Set와 List에 넣어서 중복을 관리하고, 마지막에 리턴하는 것으로 변경했다.
아래는 변경된 코드이다.
결과
소스 코드
import java.util.*;
class Solution {
public int[] solution(String s) {
List<Integer> answer = new ArrayList<>();
s = s.substring(2, s.length()-2).replace("},{", " ");
Map<Integer, String> map = new TreeMap<>();
Set<Integer> set = new HashSet<>();
String tmp[] = s.split(" ");
for(String t:tmp){
map.put(t.length(), t);
}
for(String h:map.values()){
for(String x:h.split(",")){
int z = Integer.parseInt(x);
if(!set.contains(z)){
set.add(z);
answer.add(z);
}
}
}
return answer.stream().mapToInt(a->a).toArray();
}
}
다른 접근 방식
Pattern을 사용하거나, 정규식을 통해 숫자만 가져와서 하는 방법이 있다.
알게 된 점
없음.