Vue中插槽和過濾器的深入講解
阿新 • • 發佈:2021-07-12
1. 題目
如何得到一個數據流中的中位數?如果從資料流中讀出奇數個數值,那麼中位數就是所有數值排序之後位於中間的數值。如果從資料流中讀出偶數個數值,那麼中位數就是所有數值排序之後中間兩個數的平均值。
例如,
[2,3,4]的中位數是 3
[2,3] 的中位數是 (2 + 3) / 2 = 2.5
設計一個支援以下兩種操作的資料結構:
- void addNum(int num) - 從資料流中新增一個整數到資料結構中。
- double findMedian() - 返回目前所有元素的中位數。
2. 示例
示例1:
輸入:
["MedianFinder","addNum","addNum","findMedian","addNum","findMedian"]
[[],[ 1],[2],[],[3],[]]
輸出:[null,null,null,1.50000,null,2.00000]
示例2:
輸入:
["MedianFinder","addNum","findMedian","addNum","findMedian"]
[[],[2],[],[3],[]]
輸出:[null,null,2.00000,null,2.50000]
3. 題解
最初的想法是用TreeMap來儲存資料,key為輸入,value為數量。然後在查詢的時候查詢偶數查詢第n/2個數以及n/2 + 1個數。超時。
然後使用大小堆的方式:
- 定義一個小頂堆和一個大頂堆。小頂堆儲存大的一半,大頂堆儲存小的一半。
- A儲存較大的一半,長度為N/2(N 為偶數) 或 (N + 1) / 2 (N 為奇數);
- B儲存較小的一半,長度為N/2(N 為偶數) 或 (N - 1) / 2 (N 為奇數);
4. 實現
4.1 TreeMap(超時)
1 class MedianFinder {
2
3 Map<Integer, Integer> ans;
4 int len = 0;
5
6 /** initialize your data structure here. */
7 public MedianFinder() {
8 ans = new TreeMap<>();
9 }
10
11 public void addNum(int num) {
12 ans.put(num, ans.getOrDefault(num, 0) + 1);
13 len++;
14 }
15
16 public double findMedian() {
17 int sum = 0;
18 if(len % 2 == 1) {
19 int index = len / 2 + 1;
20 for(int k : ans.keySet()) {
21 if(sum + ans.get(k) >= index) {
22 return k;
23 }
24 sum += ans.get(k);
25 }
26 } else {
27 int pre = len / 2, cur = len / 2 + 1;
28 System.out.println("輸入:" + pre + " " + cur);
29 int preValue = -50, curValue = -50;
30 for(int k : ans.keySet()) {
31 if(sum + ans.get(k) >= pre && preValue == -50) {
32 preValue = k;
33 }
34 if(sum + ans.get(k) >= cur && curValue == -50) {
35 curValue = k;
36 break;
37 }
38 sum += ans.get(k);
39 }
40 System.out.println("輸出:" + preValue + " " +curValue);
41 return (double)((preValue + curValue) / 2.0);
42 }
43 return 0;
44 }
45 }
46
47 /**
48 * Your MedianFinder object will be instantiated and called as such:
49 * MedianFinder obj = new MedianFinder();
50 * obj.addNum(num);
51 * double param_2 = obj.findMedian();
52 */
View Code
4.2 大小頂堆
1 class MedianFinder {
2 // 大小堆
3 Queue<Integer> A, B;
4 public MedianFinder() {
5 A = new PriorityQueue<>(); // 小頂堆,儲存較大的一堆
6 B = new PriorityQueue<>((x, y) -> (y - x)); // 大頂堆,儲存較小的一半
7 B = new PriorityQueue<>((x, y) -> (y - x)); // 大頂堆,儲存較小的一半
8 }
9 // 建立大小頂堆,各儲存一半:
10 // A儲存較大的一半,長度為N/2(N 為偶數) 或 (N + 1) / 2 (N 為奇數);
11 // B儲存較小的一半,長度為N/2(N 為偶數) 或 (N - 1) / 2 (N 為奇數)
12 public void addNum(int num) {
13 // A.size() != B.size(),需向B新增一個元素。實現方法:將新元素num插入A,再將A堆頂元素插入至B;
14 // A.size() == B.size(),需向A新增一個元素,實現方法:將新元素num插入B,再將B堆頂元素插入至A;
15 if(A.size() != B.size()) {
16 A.add(num);
17 B.add(A.poll());
18 } else {
19 B.add(num);
20 A.add(B.poll());
21 }
22 }
23 public double findMedian() {
24 return A.size() != B.size() ? A.peek() : (A.peek() + B.peek()) / 2.0;
25 }
26 }
27
28 /**
29 * Your MedianFinder object will be instantiated and called as such:
30 * MedianFinder obj = new MedianFinder();
31 * obj.addNum(num);
32 * double param_2 = obj.findMedian();
33 */
View Code
5. 結語
努力去愛周圍的每一個人,付出,不一定有收穫,但是不付出就一定沒有收穫! 給街頭賣藝的人零錢,不和深夜還在擺攤的小販討價還價。願我的部落格對你有所幫助(*^▽^*)(*^▽^*)!
如果客官喜歡小生的園子,記得關注小生喲,小生會持續更新(#^.^#)(#^.^#)。
但行好事 莫問前程