[프로그래머스] 같은 숫자는 싫어!

🚨문제 설명

💡푼 방법

import java.util.*;

public class Solution {
    public int[] solution(int []arr) {
        
        int num = 1;
        
        //숫자가 변경되는 횟수 +1이 총 나와야하는 수의 개수
        for(int i = 1; i < arr.length; i++){
            if(arr[i] != arr[i-1]){
                num++;
            }
        }

        //answer의 length를 num으로 지정
        int[] answer = new int[num];


        //answer의 첫번째 수와 arr의 첫번째 수는 항상 같기 떄문에 미리 넣어준다.
        answer[0] = arr[0];
        
        //초기화를 진행해줬으니 그 이후 answer와 arr이 반복문을 돌 때 1부터 돌도록 해준다.
        int n = 1;
        
        //이전 수와 지금 수가 다를 떄 answer에 지금 값을 넣어주고 n에 1을 더해준다
        for(int j = 1; j < arr.length; j++){
            if(arr[j] != arr[j-1]){
                answer[n] =arr[j];
                n++;
            }
        }
        
        System.out.println(answer);

        return answer;
    }
}

 

일단 나는 이전 숫자와 현재 숫자가 다를 경우에 num에 1을 더해주면서 answer 배열의 총 길이를 정해주었다.

그리고 answer와 arr의 0번째는 무조건 같다고 판단했기 때문에 미리 넣어주고,

그 다음 for문을 돌릴 때 j가 1부터 돌아가게해 이전 숫자와 비교하도록 했다.

비교했을 때 다르면 answer배열에 넣어주고 다음 번호로 넘어가게 했고 아니면 j의 수만 커지도록 했다.

 

난 이게 정답인가? 하면서 풀었는데 정답도 맞고 효율도 통과됐다.

효율이 통과된게 신기했고 사실 이 문제가 스택/큐 문제여서 스택과 큐를 이용해 풀어보려고했지만 잘 모르겠어서 배열로 풀었다.

 

for문이 중복으로 이루어져있어 이걸 어떻게 개선하면 좋을지 생각해봤다. 그리고 스택이나 큐를 이용해서 하는 방법도 추후를 위해 공부해두면 좋을 것 같아 개선된 방법을 찾아보기로했다.

 

🚧오답 노트

1. ArrayList

ArrayList는 배열과 달리 길이를 미리 지정해두지 않아도 된다. 그리고 배열은 수를 넣을 때 어디에 넣을지 지정해야하지만 Arraylist는 .add()를 사용하면 된다.

 

그래서 배열보다는 ArrayList를 선호하니 알아두면 좋다.

+그래도 ArrayList를 사용할 때 정해야되는 길이를 알고있으면 미리 지정하는 것이 좋다(더 빨라짐!)

import java.util.*;

public class Solution {
    public int[] solution(int []arr) {
        ArrayList<Integer> list = new ArrayList<>();
        
        // 첫 번째 원소는 항상 넣어줍니다.
        int prev = -1; // 이전 숫자가 -1일 리 없다는 가정(arr에는 자연수만 존재함)
        
        for (int n : arr) {
            // 이전 숫자와 다를 때만 리스트에 추가!
            if (n != prev) {
                list.add(n);
                prev = n; // 이전 숫자를 현재 숫자로 갱신
            }
        }
        
        // ArrayList를 다시 int[] 배열로 변환하는 과정
        int[] answer = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            answer[i] = list.get(i);
        }
        
        return answer;
    }
}

이렇게하면 num 계산을 하는 코드가 필요없어져 더욱 간결해진다.

2. Stack

이 문제에서는 큐보다는 스택을 사용하는 것이 맞다.

스택은 LIFO으로 마지막으로 후입선출이다.

그래서 스택에 들어있는 것(이전 것)과 지금 들어오는 것과 비교해 다를 경우 스택에 넣고 같을 경우 스택에 넣지 않으면 된다.

import java.util.*;

public class Solution {
    public int[] solution(int []arr) {
        Stack<Integer> stack = new Stack<>();
        
        for (int n : arr) {
            // 스택이 비어있거나, 스택의 맨 위(peek)와 현재 값이 다를 때만 넣는다!
            if (stack.isEmpty() || stack.peek() != n) {
                stack.push(n);
            }
        }
        
        // 스택에 담긴 값을 다시 배열로 옮기기
        int[] answer = new int[stack.size()];
        for (int i = stack.size() - 1; i >= 0; i--) {
            answer[i] = stack.pop();
        }
        
        return answer;
    }
}

스택에 있던 것을 다시 answer 배열로 옮길 때 후입선출이기 때문에 i를 0부터 시작하는 것이 아닌 stack.size() 부터 즉 마지막 번호부터 시작하게 만든다.