题解 | #数据流中的中位数#

数据流中的中位数

http://www.nowcoder.com/practice/9be0172896bd43948f8a32fb954e1be1

思路跟精华题解里面两个堆的一样,不过自己写了两个数组实现堆,写着写着写了好长🤣
因为数据分成两半,左半边是小一点的数,如果要取数字就要取最大的,所以是大顶堆。右半边是大一点的数,如果取数字就要取最小的,所以是小顶堆。
插入数字的时候,做了细致的分类处理,看了一下别的解答,我这个太复杂了hhh

public class Solution {
    private static int[] smallHalf = new int[501];    // 存小的一半数字,用大顶堆    
    private static int[] largeHalf = new int[501];    // 存大的一半数字,用小顶堆
    
    // 如果偶数个数字,则各存一半,否则放在小数字数组
    private static int lenSmall = 0;    // 小数字部分有几个数
    private static int lenLarge = 0;    // 大数字部分有几个数
    
    public void Insert(Integer num) {
        if (lenSmall == 0) {
            smallHalf[1] = num;
            lenSmall++;
            return;
        }
        else if (lenLarge == 0) {
            if (num >= smallHalf[1]) {
                largeHalf[1] = num;
            }
            else {
                largeHalf[1] = smallHalf[1];
                smallHalf[1] = num;
            }
            lenLarge++;
            return;
        }
        else if (num < smallHalf[1]) {
            if (lenSmall == lenLarge) {
                lenSmall++;
                smallHalf[lenSmall] = num;
                swimSmall(lenSmall);
                return;
            }
            else {
                lenLarge++;
                largeHalf[lenLarge] = smallHalf[1];
                swimLarge(lenLarge);
                
                smallHalf[1] = num;
                sinkSmall(1);
                return;
            }
        }
        
        else if (num < largeHalf[1]) {
            if (lenSmall == lenLarge) {
                lenSmall++;
                smallHalf[lenSmall] = num;
                swimSmall(lenSmall);
                return;
            }
            else {
                lenLarge++;
                largeHalf[lenLarge] = num;
                swimLarge(lenLarge);
                return;
            }
        }
        
        else {
            if (lenSmall == lenLarge) {
                lenSmall++;
                smallHalf[lenSmall] = largeHalf[1];
                swimSmall(lenSmall);
                
                largeHalf[1] = num;
                sinkLarge(1);
                return;
            }
            else {
                lenLarge++;
                largeHalf[lenLarge] = num;
                swimLarge(lenLarge);
                return;
            }
        }
    }

    public Double GetMedian() {
        // 奇数个数字
        if (lenSmall > lenLarge) {
            return (double)smallHalf[1];
        }
        
        return (smallHalf[1] + largeHalf[1]) / 2.0;
    }

    private void swimSmall(int k) {
        while (k > 1) {
            if (smallHalf[k] > smallHalf[k/2]) {
                swap(smallHalf, k, k/2);
                k /= 2;
            }
            else {
                break;
            }
        }
    }
    
    private void swimLarge(int k) {
        while (k > 1) {
            if (largeHalf[k] < largeHalf[k/2]) {
                swap(largeHalf, k, k/2);
                k /= 2;
            }
            else {
                break;
            }
        }
    }
    
    private void sinkSmall(int k) {
        while (2*k <= lenSmall) {
            int t = 2 * k;
            if (t+1 <= lenSmall && smallHalf[t] < smallHalf[t+1]) {
                t++;
            }
            if (smallHalf[k] >= smallHalf[t]) {
                break;
            }
            swap(smallHalf, k, t);
            k = t;
        }
    }
    
    private void sinkLarge(int k) {
        while (2*k <= lenLarge) {
            int t = 2 * k;
            if (t+1 <= lenLarge && largeHalf[t] > largeHalf[t+1]) {
                t++;
            }
            if (largeHalf[k] <= largeHalf[t]) {
                break;
            }
            swap(largeHalf, k, t);
            k = t;
        }
    }
    
    private void swap(int[] arr, int i, int j) {
        int t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
    }
}


全部评论

相关推荐

1 收藏 评论
分享
牛客网
牛客企业服务