prgms.12906 - 같은 숫자는 싫어

연속한 같은 숫자를 제거하는 문제이다. 각종 사이트에 이와 비슷한 문제들을 많이 본 것 같다. 하지만 매번 풀때마다 새로운 머리가짐이다. 😂

이 문제를 푸는 방법은 아주 다양하다.

  1. 배열의 인접한 값을 서로 비교하면서 서로 다를때만 추가하는 방식
  2. String으로 배열 요소를 추가한뒤에 replaceAll()과 정규식으로 하나 이상의 중복문자를 대체하는 방식

아마도 두 번째 방식은 상당히 시간이 많이 걸려서 효율성 테스트에서 좋은 점수를 받지는 못할 것이다. 따라서 첫 번째 방식으로 작성해보았다.

첫번째 실패

중복제거 라는 키워드를 보자마자 Set을 사용하려고 달려들었다. 그 중에서도 순서유지를 보장하는 LinkedHashSet까지 사용해보았으나 실패. 왜냐하면 [1,1,2,2,3,3,1,1] 에서 마지막에 1이 다시 나오더라도 이미 set에 있어서 추가되지 않는 문제가 발생하기 때문이다. 즉, [1,2,3,1] 이 아니라 [1,2,3]이 결과로 출력된다.

class Solution {
    public Integer[] solution(int []arr) {
        Set<Integer> set = new LinkedHashSet<>();
        for (int num : arr){
            set.add(num);
        }
        Integer[] answer = new Integer[set.size()];
        set.toArray(answer);
        return answer;
    }
}

두번째 성공

결국 그냥 인접한 배열 요소를 비교하는 수 밖에 없다. 처음에는 단순히 비교를 하면서 다를때 추가했지만, 계속되는 테스트케이스 실패로 예외처리 코드를 하나씩 넣어서 다소 지저분해졌다.

class Solution {
    public List<Integer> solution(int[] arr) {
        if (arr.length == 0) return null;
        List<Integer> answer = new ArrayList<>();
        for (int i = 0; i < arr.length - 1; i++) {
            if (arr[i] != arr[i + 1]) {
                answer.add(arr[i]);
            }
        }
        if (answer.size() == 0){
            answer.add(arr[0]);
            return answer;
        }
        if (answer.get(answer.size() - 1) != arr[arr.length - 1]) {
            answer.add(arr[arr.length - 1]);
        }
        return answer;
    }
}

다른 사람의 풀이

메커니즘은 동일하나 for-each문으로 좀 더 간결해졌다. 바로 이전의 숫자를 preNum이라는 임시변수에 저장함으로써 끝부분의 처리코드도 필요없다.

import java.util.*;

public class Solution {
	public List<Integer> solution(int[] arr) {
        if (arr.length == 0) return null;
        List<Integer> answer = new ArrayList<>();
        int preNum = 10;
        for(int num : arr) {
            if(preNum != num) answer.add(num);
            preNum = num;
        }     
        return answer;
    }
}