마이의 개발 블로그

[프로그래머스] 뒤에 있는 큰 수 찾기 (Java) 본문

코딩테스트/프로그래머스

[프로그래머스] 뒤에 있는 큰 수 찾기 (Java)

개발자마이 2023. 3. 15. 11:57
반응형
 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

접근 방식

이중 반복문으로 테케는 풀렸으나 당연히 시간초과에 걸렸고, 스택으로 풀어야 해결된다는 힌트를 보고 몇 날 며칠을 고민했던 문제다. 다른 사람들의 접근법을 보고난 후에도 로직을 이해하기 위해 노력해야했는데 막상 이해하고나니 너무나 간단한 문제였다. 이런 유형에서 스택을 사용하는 이유는 탐색 도중 구간별 변화를 감지했을 때에만 그 구간에서의 결과값이 도출되기 때문이다. 즉, 구간별 변화(뒤에 나보다 큰 수가 존재하는 것)가 일어나지 않으면 결과값을 도출할 수 없고(-1), 변화가 감지되었을 때에만 탐색된 구간에 대한 결과값을 저장(뒤에 있는 가장 가까운 큰 수를 저장)할 수 있다. 이 문제는 주식 가격이 떨어지지않은 구간의 길이를 구해야하는 주식가격 문제와도 비슷한 유형이라고 볼 수 있는데, 당시에는(꽤 오래전에 풀어놓은 문제임) 이게 왜 스택/큐 문제로 분류되어있는지 이해하지 못하고 반복문으로 풀어냈던 기억이 있다. 이 문제도 스택을 사용하지 않고 반복문으로도 충분히 풀어낼 수 있는 문제라고 판단되어 나중에 반복문으로도 구현해보려고 한다 (아래 추가함).

로직 설명

- 답변 배열 생성 및 -1로 초기화 

- numbers 배열을 탐색하며:

1) 구간별 변화가 감지된 경우(현재 숫자가 직전 숫자보다 큰 경우), 해당 구간(스택의 인덱스에 해당하는 숫자가 현재 숫자보다 작은 동안 스택을 연속하여 pop)의 모든 답변을 현재 숫자로 저장

2) 스택에 현재 인덱스 저장(push)

Note

- 작성하고보니 리팩토링으로 좀 더 간결하게 만들 수 있는 문제라는 생각이 든다. 

import java.util.*;

class Solution {
    public int[] solution(int[] numbers) {
        int[] answer = new int[numbers.length];
        
        Arrays.fill(answer, -1);
        
        Stack<Integer> stack = new Stack<>();
        
        for(int i = 0; i < numbers.length; i++){
            if(stack.isEmpty() || numbers[i] < numbers[i-1]){
                stack.push(i);
            }else{
                while(!stack.isEmpty() && numbers[i] > numbers[stack.peek()]){
                    answer[stack.pop()] = numbers[i];
                }
                stack.push(i);
            }
        }
        
        return answer;
    }
}

2023.3.15 리팩토링

import java.util.*;

class Solution {
    public int[] solution(int[] numbers) {
        int[] answer = new int[numbers.length];
        
        Arrays.fill(answer, -1);
        
        Stack<Integer> stack = new Stack<>();
        
        for(int i = 0; i < numbers.length; i++){
            if(!stack.isEmpty() && numbers[i] > numbers[i-1]){
                while(!stack.isEmpty() && numbers[i] > numbers[stack.peek()]){
                    answer[stack.pop()] = numbers[i];
                } 
            }
            stack.push(i);
        }
        
        return answer;
    }
}

2023.3.15 반복문으로 재작성 (더 빠름)

import java.util.*;

class Solution {
    public int[] solution(int[] numbers) {
        int[] answer = new int[numbers.length];
        
        for(int i = 0; i < numbers.length - 1; i++){
            if(numbers[i + 1] > numbers[i]){
                int idx = i;
                int biggerNum = numbers[i + 1];
                while(idx >= 0 && biggerNum > numbers[idx]){
                    if(answer[idx] == 0){
                        answer[idx] = biggerNum;    
                    }
                    idx--;
                } 
            }
        }
        
        for(int i = 0; i < answer.length; i++){
            if(answer[i] == 0){
                answer[i] = -1;
            }
        }
        
        return answer;
    }
}

반응형
Comments