ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [슬라이딩 윈도우 + deque] 백준 11003번
    책/DoIt 알고리즘 코딩테스트 2024. 10. 27. 14:56

     

    문제

    1. 숫자 배열 크기 + 범위 크기가 주어짐
    2. 숫자 배열이 주어짐
    3. 숫자배열에서 범위만큼 움직이며, 그때마다 최소값을 저장
    문제 조건 : ( 1 <= 범위크기 <= 숫자 개수 <=  5,000,000 ) +  2.4초(제한시간)

     

    문제분석

    • 범위 크기 이동만큼 최소값 탐색
      • 슬라이딩 윈도우 : 2개의 포인터를 잡고, 이동시키며 최소값 탐색
    • 범위크기 및 숫자개수 최대치가 5,000,000이므로 시간복잡도를 O(n) 초과하여 잡을 수가 없음 (시간 초과)
      • 기본 정렬 시간 복잡도 : O(nlogn)
      • 일반적인 정렬알고리즘으로 풀지 못하므로, 덱(deque)을 도입
    Deque (덱)
     - 앞쪽에서 추가/삭제 가능, 뒷쪽에서도 추가/삭제 가능
    [구조]
        Add    ->                                               -> Remove
                       Front , 값1, 값2, 값3 ..., End
    remove <-                                               <- Add

     

    예시)
    숫자배열 크기 : 5  / 범위크기 : 3 / 숫자배열 : 1 5 2 3 6
    (주요 포인트 : 그 다음 deque에 들어오는 값보다 이전에 들어있던 값이 더 크면 삭제 )
    ex) (1,1) (2,5) , (3,2) ... 에서 범위가 3이므로 3개묶음으로 가게된다 (그러면 (3,2)가 존재하므로 (2,5)는 최소값이 영영 될수가 없다)

    [덱] : (인덱스번호, 값) 
    첫번째 : (1,1)             -> 1 추출
    두번째 : (1,1) (2,5)    -> 1 추출
    세번째 : (1,1) (2,5) (3,2) -> 1 추출 // 3 인덱스의 값이 , 2 인덱스 값보다 작으므로 2인덱스 삭제
    네번째 : (3,2) (4,3) -> 2 추출 // 인덱스번호가 4이므로, 첫번째 인덱스는 제거 ( 범위크기 : 3 )
    ...

     

    수도코드

    N(데이터 개수), L(최소값을 구하는 범위)
    Deque<Node> mydeque (데이터를 담을 덱 자료구조)
    배열 선언
    
    for( N 만큼 반복 )
    {
        now (현재 데이터값)
        덱의 마지막 위치에서 now보다 큰값 제거
        덱의 마지막 위치에 now값 저장
        덱의 1번째 위치에서부터 L의 범위를 벗어난 값을 덱에서 제거
        덱의 1번째 데이터 출력
    }
    
    덱에 저장할 노드클래스 별도 생성
    노드 클래스 (index, value) 저장

     

    구현

    • BufferedWriter
      • System.out.print을 사용하여, 제출할경우 시간초과 발생!
      • 버퍼로 모아서 한번에 출력하는 것이 시간 관리에 효율적임 (500만이라는 큰 수의 테스트 과정도 거칠수 있으니..)
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.util.StringTokenizer;
    import java.util.Deque;
    import java.util.LinkedList;
    
    
    public class App {
        public static void main(String[] args) throws Exception {
            BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
            StringTokenizer st = new StringTokenizer(buf.readLine());
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    
            int arraySize;
            int range;
            
            
            if (st.hasMoreTokens()){
                arraySize = Integer.parseInt(st.nextToken());
                range = Integer.parseInt(st.nextToken());
            }else{
                System.out.println("StringTokenizer Error!");
                throw new RuntimeException();
            } 
            
            int[] arr = new int[arraySize];
            int now = 0;
            Deque<Node> myDeque = new LinkedList<>();
    
            st = new StringTokenizer(buf.readLine());
            for(int i =0; i< arraySize; i++){
                
                now = Integer.parseInt(st.nextToken());
    
                while(!myDeque.isEmpty() && myDeque.getLast().value > now){
                    myDeque.removeLast();
                }
                myDeque.addLast(new Node(i, now));
    
                if (myDeque.getFirst().index <= i-range){
                    myDeque.removeFirst();
                }
    
    
                bw.write(myDeque.getFirst().value + " ");
            }
    
            bw.flush();
            bw.close();
    
            
            
            
    
        }
    
    
        public static class Node{
            private int index;
            private int value;
    
            public Node(int index, int value){
                this.index = index;
                this.value = value;
            }
        }
    }

    ' > DoIt 알고리즘 코딩테스트' 카테고리의 다른 글

    [스택] 백준 17298  (0) 2024.10.30
    [스택] 백준 1874번  (0) 2024.10.29
    [슬라이딩윈도우] 백준 12891번  (0) 2024.10.24
    [투포인터] 백준 1253  (0) 2024.10.23
    [투포인터] 백준 1940번  (0) 2024.10.22
Designed by Tistory.