처음에는 단순하게 maxHeap을 이용해서 O(N)만에 풀면 되지 않을까 생각했다.

윈도우를 maxHeap에 넣고 움직이면서 맨 앞의 값은 빼고, 뒤에 새로 들어오는 값은 더해주는 방식으로 구현했다.

import java.util.*;
class Solution {
	public int[] maxSlidingWindow(int[] nums, int k) {
		int length = nums.length;
		int answer[] = new int[length - k + 1];

		PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(Collections.reverseOrder());
		for (int i = 0; i < k; i++) {
			maxHeap.add(nums[i]);
		}
		answer[0] = maxHeap.peek();

		for (int i = 1; i < length - k + 1; i++) {
			Integer remove = nums[i - 1];
			int add = nums[i + k - 1];
			maxHeap.remove(remove);
			maxHeap.add(add);

			answer[i] = maxHeap.peek();
		}

		return answer;
	}
}

 

결과는 Hard 문제 답게 TLE가 떴다...ㅠ

다시 문제 조건을 자세히 살펴봤다. 문제 조건은 아래와 같다.

  • 1 <= nums.length <= 10^5
  • -10^4 <= nums[i] <= 10^4
  • 1 <= k <= nums.length

내가 구현한 코드가 O(N)이 맞다면 nums.length<=10^5이기 때문에 시간내에 동작해야 했다.

다시 생각 해 보니 maxHeap에 넣고 빼는 동작이 logk씩 일어나기 때문에 O(NlogK)로 시간초과가 날 수 있다는 점을 생각하지 못했다.

뭔가 윈도우를 하나씩 옮기는 방법은 맞는 것 같으니, 최댓값을 구할 때 O(logK)보다 줄일 수 있는지 생각해 봤다.

 

일단은 문자열을 넣고 뺄때 힙구조가 아닌 Deque를 사용하는게 좋을 것 같았다. Deque는 맨앞과 맨뒤의 요소를 넣고 뺄 때 O(1)이 걸린다.

문제 풀이 방법은 아래와 같다.

 

1. 위의 경우와 마찬가지로 첫 k개는 Deque에 넣고 최댓값을 구한다.

2. 윈도우를 움직인다. 이 때,

  • deque에는 index를 넣어두고, 현재 윈도우 안의 요소가 될 수 있는 인덱스들만 넣어 둔다.
  • 새로 집어 넣는 값에 비해 작은 값들을 앞에서 부터 다 뺀다. 왜냐면 윈도우는 오른쪽으로 움직이고 있고, 현재 넣는 값보다 작은 기존의 deque에 있는 값은 영원히 최대값이 될 수 없기 때문이다.

 

아래는 구현한 코드이다.

import java.util.*;
class Solution {
	public void moveWindow(int i, int k, ArrayDeque<Integer> deque, int[] nums) {
		if (!deque.isEmpty() && deque.getFirst() == i - k) {
			deque.removeFirst();
		}

		while (!deque.isEmpty() && nums[i] > nums[deque.getLast()]) {
			deque.removeLast();
		}
	}

	public int[] maxSlidingWindow(int[] nums, int k) {
		ArrayDeque<Integer> deque = new ArrayDeque<Integer>();
		int length = nums.length;
		if (length * k == 0) {
			return new int[0];
		}
		if (k == 1) {
			return nums;
		}

		int maxIndex = 0;
		for (int i = 0; i < k; i++) {
			moveWindow(i, k, deque, nums);
			deque.addLast(i);

			if (nums[i] > nums[maxIndex]) {
				maxIndex = i;
			}
		}

		int[] answer = new int[length - k + 1];
		answer[0] = nums[maxIndex];

		for (int i = k; i < length; i++) {
			moveWindow(i, k, deque, nums);
			deque.addLast(i);
			answer[i - k + 1] = nums[deque.getFirst()];
		}
		return answer;
	}
}

'알고리즘 공부 > leetcode' 카테고리의 다른 글

leetcode: Decode String  (0) 2021.02.14
leetcode: Task Scheduler  (0) 2021.02.07
leetcode: Longest Increasing Subsequence  (0) 2021.02.07
leetcode: Jump Game II  (0) 2021.01.31
leetcode: Longest Increasing Path in a Matrix  (0) 2021.01.31

+ Recent posts