Leetcode Java Sliding Window Median
업데이트:
문제
코드
class Solution {
public double[] medianSlidingWindow(int[] nums, int k) {
int[] part = new int[k];
double[] result = new double[nums.length - k + 1];
for (int i = 0; i < k; i++) {
part[i] = nums[i];
}
Arrays.sort(part);
result[0] = this.getMedian(part, k);
for (int i = k, j = 1; i < nums.length; i++, j++) {
this.delete(part, k, nums[i - k]);
this.insert(part, k, nums[i]);
result[j] = this.getMedian(part, k);
}
return result;
}
private double getMedian(int[] part, int k) {
if (k % 2 == 1) {
return (double) part[k / 2];
} else {
return (part[(k / 2) - 1] / 2.0) + (part[k / 2] / 2.0);
}
}
private void delete(int[] part, int k, int value) {
int left = 0;
int right = k;
while (left < right) {
int mid = left + (right - left) / 2;
if (part[mid] == value) {
System.arraycopy(part, mid + 1, part, mid, k - (mid + 1));
part[k - 1] = value;
return;
}
if (part[mid] < value) {
left = mid + 1;
} else {
right = mid;
}
}
}
private void insert(int[] part, int k, int value) {
int left = 0;
int right = k - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (part[mid] < value) {
left = mid + 1;
} else {
right = mid;
}
}
System.arraycopy(part, left, part, left + 1, (k - 1) - left);
part[left] = value;
}
}
결과
설명
-
정수의 배열인 nums를 이용하여 앞에서 부터 k개 씩 묶어 각각의 중앙값들을 찾아 반환하는 문제이다.
- 문제 풀이에 필요한 변수를 정의한다.
- part는 k개의 정수를 넣어 중앙값을 탐색하기 위한 배열로, k 크기로 정의하여 nums의 0 번째 값부터 k 번째 값까지 넣어준다.
- result는 각 중앙값을 넣을 배열로, $nums.length - k + 1$ 크기로 정의한다.
- k개를 묶어 하나의 중앙값이 나오므로, 배열의 크기에서 $k - 1$을 뺀 값만큼 수의 중앙값이 나오게된다.
- part를 오름차순 정렬하고 result의 첫 값에 3번에서 정의한 getMedian(int[] part, int k) 메서드의 결과를 넣어준다.
- i는 k, j는 1부터 i가 nums의 길이 미만까지 i와 j를 증가시키며 아래를 수행한다.
- 4번에서 정의한 delete(int[] part, int k, int value) 메서드를 수행하여 part에 nums의 $i - k$번째 값을 제거해준다.
- 5번에서 정의한 insert(int[] part, int k, int value) 메서드를 수행하여 part에 nums의 i번째 값을 넣어준다.
- result의 j번째 위치에 3번에서 정의한 getMedian(int[] part, int k) 메서드를 수행한 결과를 넣어준다.
- 반복이 완료되면 중앙값들을 넣은 result를 주어진 문제의 결과로 반환한다.
- 중앙값을 계산하기 위한 getMedian(int[] part, int k) 메서드를 정의한다.
- k가 홀수인 경우, part의 $\frac{size}{2}$번째 값을 double 형으로 변환 후 반환한다.
- k가 짝수인 경우, part의 $\frac{size}{2} - 1$번째 값을 2.0으로 나눈 값과 part의 $\frac{size}{2}$번째 값을 2.0으로 나눈 값을 더해서 반환한다.
- part 내 value에 대한 값을 제거하기 위한 delete(int[] part, int k, int value) 메서드를 정의한다.
- left를 0으로, right를 k로 넣어 초기화한다.
- left가 right보다 작을 때 까지 반복하여 아래를 수행한다.
- mid에 $left + \frac{right - left}{2}$의 결과를 넣어 탐색 위치를 설정한다.
- part의 mid번째 값이 value인 경우, part의 $mid + 1$번째 값부터 $k - (mid + 1)$개의 값들을 part의 mid번째 값 위치부터 넣어주고 part의 $k - 1$번째 값에 value를 넣어주고 수행을 멈춘다.
- part의 mid번째 값이 value보다 작은 경우, left에 $mid + 1$을 넣고 아니면 right에 mid를 넣어 범위를 좁혀준다.
- part 내 value를 넣기 위한 insert(int[] part, int k, int value) 메서드를 정의한다.
- left를 0으로, right를 $k - 1$로 넣어 초기화한다.
- left가 right보다 작을 때 까지 반복하여 아래를 수행한다.
- mid에 $left + \frac{right - left}{2}$의 결과를 넣어 탐색 위치를 설정한다.
- part의 mid번째 값이 value보다 작은 경우, left에 $mid + 1$을 넣고 아니면 right에 mid를 넣어 범위를 좁혀준다.
- 반복이 완료되면 part의 left 번째 값부터 $(k - 1) - left$번째 값까지 part의 $left + 1$번쨰 위치부터 넣어주고 part의 left번째 자리에 value를 넣어준다.
소스
Sample Code는 여기에서 확인 가능합니다.
댓글남기기