Skip to content

Commit 2927ff0

Browse files
committed
fd
1 parent e380fbc commit 2927ff0

File tree

3 files changed

+151
-57
lines changed

3 files changed

+151
-57
lines changed
Lines changed: 62 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,88 @@
11
package com.inuker.solution;
22

33
import java.util.Collections;
4+
import java.util.Comparator;
5+
import java.util.Map;
46
import java.util.TreeMap;
57

68
/**
79
* Created by liwentian on 2017/9/12.
10+
* https://leetcode.com/articles/sliding-window-median/
11+
* 和 #295 Find Median from Data Stream 比较类似
812
*/
913

1014
public class SlidingWindowMedian {
1115

16+
/**
17+
* 这题如果用PriorityQueue则复杂度为O(nk),因为其删除复杂度为O(n)
18+
* 改为TreeMap会降为O(nlgk)
19+
*/
1220
public double[] medianSlidingWindow(int[] nums, int k) {
13-
double[] res = new double[nums.length - k + 1];
14-
TreeMap<Integer, Integer> minHeap = new TreeMap<Integer, Integer>();
15-
TreeMap<Integer, Integer> maxHeap = new TreeMap<Integer, Integer>(Collections.reverseOrder());
21+
MyMap up = new MyMap();
22+
MyMap down = new MyMap(Comparator.reverseOrder());
23+
double[] result = new double[nums.length - k + 1];
24+
for (int i = 0; i < nums.length; i++) {
25+
up.myAdd(nums[i]);
26+
down.myAdd(up.myPollFirst());
1627

17-
int minHeapCap = k / 2; //smaller heap when k is odd.
18-
int maxHeapCap = k - minHeapCap;
28+
if (i >= k) {
29+
if (up.containsKey(nums[i - k])) {
30+
up.myRemove(nums[i - k]);
31+
} else {
32+
down.myRemove(nums[i - k]);
33+
}
34+
}
1935

20-
for (int i = 0; i < k; i++) {
21-
maxHeap.put(nums[i], maxHeap.getOrDefault(nums[i], 0) + 1);
36+
if (up.size < down.size) {
37+
up.myAdd(down.myPollFirst());
38+
}
39+
if (i >= k - 1) {
40+
result[i - k + 1] = up.size == down.size
41+
? ((double) up.firstKey() + down.firstKey()) / 2 : up.firstKey();
42+
}
2243
}
23-
int[] minHeapSize = new int[]{0};
24-
int[] maxHeapSize = new int[]{k};
25-
for (int i = 0; i < minHeapCap; i++) {
26-
move1Over(maxHeap, minHeap, maxHeapSize, minHeapSize);
44+
return result;
45+
}
46+
47+
class MyMap extends TreeMap<Integer, Integer> {
48+
int size;
49+
50+
MyMap() {
51+
super();
2752
}
2853

29-
res[0] = getMedian(maxHeap, minHeap, maxHeapSize, minHeapSize);
30-
int resIdx = 1;
54+
MyMap(Comparator<Integer> comparator) {
55+
super(comparator);
56+
}
3157

32-
for (int i = 0; i < nums.length - k; i++) {
33-
int addee = nums[i + k];
34-
if (addee <= maxHeap.keySet().iterator().next()) {
35-
add(addee, maxHeap, maxHeapSize);
36-
} else {
37-
add(addee, minHeap, minHeapSize);
38-
}
58+
void myAdd(int n) {
59+
put(n, getOrDefault(n, 0) + 1);
60+
size++;
61+
}
3962

40-
int removee = nums[i];
41-
if (removee <= maxHeap.keySet().iterator().next()) {
42-
remove(removee, maxHeap, maxHeapSize);
63+
boolean myRemove(int n) {
64+
int count = getOrDefault(n, 0);
65+
if (count == 0) {
66+
return false;
67+
}
68+
if (count == 1) {
69+
remove(n);
4370
} else {
44-
remove(removee, minHeap, minHeapSize);
71+
put(n, count - 1);
4572
}
73+
size--;
74+
return true;
75+
}
4676

47-
//rebalance
48-
if (minHeapSize[0] > minHeapCap) {
49-
move1Over(minHeap, maxHeap, minHeapSize, maxHeapSize);
50-
} else if (minHeapSize[0] < minHeapCap) {
51-
move1Over(maxHeap, minHeap, maxHeapSize, minHeapSize);
77+
int myPollFirst() {
78+
Map.Entry<Integer, Integer> entry = firstEntry();
79+
if (entry.getValue() == 1) {
80+
pollFirstEntry();
81+
} else {
82+
put(entry.getKey(), entry.getValue() - 1);
5283
}
53-
54-
res[resIdx] = getMedian(maxHeap, minHeap, maxHeapSize, minHeapSize);
55-
resIdx++;
84+
size--;
85+
return entry.getKey();
5686
}
57-
return res;
58-
}
59-
60-
public double getMedian(TreeMap<Integer, Integer> bigHeap, TreeMap<Integer, Integer> smallHeap, int[] bigHeapSize, int[] smallHeapSize) {
61-
return bigHeapSize[0] > smallHeapSize[0] ? (double) bigHeap.keySet().iterator().next() : ((double) bigHeap.keySet().iterator().next() + (double) smallHeap.keySet().iterator().next()) / 2.0;
62-
}
63-
64-
//move the top element of heap1 to heap2
65-
public void move1Over(TreeMap<Integer, Integer> heap1, TreeMap<Integer, Integer> heap2, int[] heap1Size, int[] heap2Size) {
66-
int peek = heap1.keySet().iterator().next();
67-
add(peek, heap2, heap2Size);
68-
remove(peek, heap1, heap1Size);
69-
}
70-
71-
public void add(int val, TreeMap<Integer, Integer> heap, int[] heapSize) {
72-
heap.put(val, heap.getOrDefault(val, 0) + 1);
73-
heapSize[0]++;
74-
}
75-
76-
public void remove(int val, TreeMap<Integer, Integer> heap, int[] heapSize) {
77-
if (heap.put(val, heap.get(val) - 1) == 1) heap.remove(val);
78-
heapSize[0]--;
7987
}
8088
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package com.inuker.test;
2+
3+
import java.util.Comparator;
4+
import java.util.Map;
5+
import java.util.TreeMap;
6+
7+
/**
8+
* Created by liwentian on 2017/12/5.
9+
*/
10+
11+
public class Test2 {
12+
13+
public double[] medianSlidingWindow(int[] nums, int k) {
14+
MyMap up = new MyMap();
15+
MyMap down = new MyMap(Comparator.reverseOrder());
16+
double[] result = new double[nums.length - k + 1];
17+
for (int i = 0; i < nums.length; i++) {
18+
up.myAdd(nums[i]);
19+
down.myAdd(up.myPollFirst());
20+
21+
if (i >= k) {
22+
if (up.containsKey(nums[i - k])) {
23+
up.myRemove(nums[i - k]);
24+
} else {
25+
down.myRemove(nums[i - k]);
26+
}
27+
}
28+
29+
if (up.size < down.size) {
30+
up.myAdd(down.myPollFirst());
31+
}
32+
if (i >= k - 1) {
33+
result[i - k + 1] = up.size == down.size
34+
? ((double) up.firstKey() + down.firstKey()) / 2 : up.firstKey();
35+
}
36+
}
37+
return result;
38+
}
39+
40+
class MyMap extends TreeMap<Integer, Integer> {
41+
int size;
42+
43+
MyMap() {
44+
super();
45+
}
46+
47+
MyMap(Comparator<Integer> comparator) {
48+
super(comparator);
49+
}
50+
51+
void myAdd(int n) {
52+
put(n, getOrDefault(n, 0) + 1);
53+
size++;
54+
}
55+
56+
boolean myRemove(int n) {
57+
int count = getOrDefault(n, 0);
58+
if (count == 0) {
59+
return false;
60+
}
61+
if (count == 1) {
62+
remove(n);
63+
} else {
64+
put(n, count - 1);
65+
}
66+
size--;
67+
return true;
68+
}
69+
70+
int myPollFirst() {
71+
Map.Entry<Integer, Integer> entry = firstEntry();
72+
if (entry.getValue() == 1) {
73+
pollFirstEntry();
74+
} else {
75+
put(entry.getKey(), entry.getValue() - 1);
76+
}
77+
size--;
78+
return entry.getKey();
79+
}
80+
}
81+
}

test/src/main/java/com/inuker/test/main.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,23 @@
1515
import java.util.LinkedHashMap;
1616
import java.util.LinkedList;
1717
import java.util.List;
18+
import java.util.Map;
1819
import java.util.PriorityQueue;
1920
import java.util.Queue;
2021
import java.util.Random;
2122
import java.util.Set;
2223
import java.util.Stack;
2324
import java.util.TreeMap;
25+
import java.util.TreeSet;
2426

2527
public class main {
2628

2729
public static void main(String[] args) {
28-
Test test = new Test();
29-
test.call("hello");
30-
test.call("how");
30+
double[] f = new Test2().medianSlidingWindow(new int[] {
31+
Integer.MAX_VALUE, 1, 2, 3, 4, 5, 6, 7, Integer.MAX_VALUE
32+
}, 2);
33+
for (double d : f) {
34+
System.out.print(d + " ");
35+
}
3136
}
3237
}

0 commit comments

Comments
 (0)