查找正在运行的中位数

时间:2016-12-27 19:36:09

标签: c++ algorithm heap median

我必须根据这个问题找到正在运行的中位数: https://www.hackerrank.com/challenges/ctci-find-the-running-median

我正在尝试实施两堆。存储小于当前中位数的元素的最小堆和存储大于当前中位数的项的最大堆。

中位数不断变化,两个堆中元素数量的差异不超过1.

但我的代码却未被接受。但它通过了我能想到的测试用例。

请仅阅读主要功能和更新中位数功能! 任何帮助表示赞赏。

#include<bits/stdc++.h>
#define pb push_back
using namespace std;

class max_heap{
private:
vector<int> items;
int size;

public:
max_heap(){
    size=0;
}
int left(int parent){   return (parent*2 + 1);  }
int right(int parent){  return (parent*2 + 2);  }
int parent(int pos){    return pos<=0 ? 0 : (pos-1)/2;      }
int getmax(){           return items[0];            }
int peek(int pos){  return items[pos];}
int length(){           return items.size();}


void swap(int pos1, int pos2){
    int tmp=items[pos1];
    items[pos1]=items[pos2];
    items[pos2]=tmp;
    return;
}
void insert(int key)
{

    if(items.size()==size)
        items.pb(key);
    else
        items[size]=key;

    //fixing items property
    int tmp=size;
    while(items[0]!=key && items[parent(tmp)] < key ){
        swap( parent(tmp), tmp);

        tmp=parent(tmp);
    }
    size++;

}

int pop(){

    if(size==0)
        return 0;
    int ans=getmax();
    size--;
    items[0]=items[size];

    //fix items
    int i=0;
    while(i<size-1){
        bool a = items[i] < items[right(i)];
        bool b = items[i] < items[left(i)];

        if( a && b)
        {
            if( items[left(i)] < items[right(i)] )
                swap(i,left(i));
            else swap(i,right(i));

        }
        else if(a)
            swap(i,right(i));
        else if(b)
            swap(i,left(i));
        else break;



    }
    return ans;
}

void print(){
    for (int i = 0; i < items.size(); ++i)
            cout<<items[i]<<" ";
    cout<<endl;
}
};

class min_heap{
private:
vector<int> items;
int size;

public:
min_heap(){
    size=0;
}
int left(int parent){   return (parent*2 + 1);  }
int right(int parent){  return (parent*2 + 2);  }
int parent(int pos){    return pos<=0 ? 0 : (pos-1)/2;      }
int getmin(){           return items[0];            }
int peek(int pos){  return items[pos];}
int length(){           return items.size();}


void swap(int pos1, int pos2){
    int tmp=items[pos1];
    items[pos1]=items[pos2];
    items[pos2]=tmp;
    return;
}
void insert(int key)
{

    if(items.size()==size)
        items.pb(key);
    else
        items[size]=key;

    //fixing items property
    int tmp=size;
    while(items[0]!=key && items[parent(tmp)] > key ){
        swap( parent(tmp), tmp);

        tmp=parent(tmp);
    }
    size++;

}

int pop(){

    if(size==0)
        return 0;
    int ans=getmin();
    size--;
    items[0]=items[size];

    //fix items
    int i=0;
    while(i<size-1){
        bool a = items[i] > items[right(i)];
        bool b = items[i] > items[left(i)];

        if( a && b)
        {
            if( items[left(i)] < items[right(i)] )
                swap(i,left(i));
            else swap(i,right(i));

        }
        else if(a)
            swap(i,right(i));
        else if(b)
            swap(i,left(i));
        else break;



    }
    return ans;
}

void print(){
    for (int i = 0; i < items.size(); ++i)
            cout<<items[i]<<" ";
    cout<<endl;
}
};

double update_median(int element, int median, min_heap &mn_heap, max_heap &mx_heap)
{

int path = mx_heap.length() - mn_heap.length();
    double ans=0.0;

switch(path){

    case 0:

    if( element >  median ){
        //push to right heap..ie the min heap
        mn_heap.insert(element);
        ans= mn_heap.getmin();
    }
    else
    {
        //push to left heap....ie max heap
        mx_heap.insert(element);
        ans= mx_heap.getmax();
    }

    break;

    case 1:     //max heap is greater ie left

    if( element >  median )
    {   //push to right heap...min heap

        mn_heap.insert(element);
        ans=(mn_heap.getmin() + mx_heap.getmax()) / 2.0;

    }

    else
    {
        mn_heap.insert(mx_heap.pop());
        mx_heap.insert(element);
        ans= (mn_heap.getmin() + mx_heap.getmax()) / 2.0;
    }

    break;


    case -1: // min heap greater ie right

    if( element >  median )
    {   //push to right heap...min heap

        mx_heap.insert(mn_heap.pop());
        mn_heap.insert(element);
        ans=(mn_heap.getmin() + mx_heap.getmax()) / 2.0;

    }

    else
    {

        mx_heap.insert(element);
        ans= (mn_heap.getmin() + mx_heap.getmax()) / 2.0;

    }

    break;




}

return ans;

}

int main(){

    cout.sync_with_stdio(false);
    int el;
    cin>>el;

    double median=0.0;

    min_heap *a = new min_heap(); //items less than median
    max_heap *b = new max_heap(); //items more than median


    while(el--){
        int element;
        cin>>element;

        median= update_median(element,median,*a,*b);

        printf("%.1lf\n", median);
    }
}

2 个答案:

答案 0 :(得分:0)

我认为问题出在pop实施的max_heap方法中。你有:

    if( a && b)
    {
        if( items[left(i)] < items[right(i)] )
            swap(i,left(i));
        else swap(i,right(i));

    }

这总是将父母与两个孩子的较小交换。在最大堆中,您希望将父级与两个子级的较大交换。您的min_heap实现也会将父级与两个孩子中较小的一个交换,这是正确的。

答案 1 :(得分:0)

使用Java查找运行中值-Hackerrank解决方案

package com.syed.test;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;

public class Solution {

    static double[] runningMedian(int[] a) {

        int[] temp = new int[a.length];
        double[] resultArray = new double[a.length];
        int counter = 0;

        for (int i = 0; i < a.length; i++) {
            temp[i] = a[i];
            counter++;

            if (i == 0) {
                resultArray[i] = (double) temp[i];
                System.out.println("i : " + i + "  " + Arrays.toString(temp));
            } else {

                Arrays.sort(temp, 0, i + 1);
                System.out.println("i : " + i + "  " + Arrays.toString(temp));

                int val = counter / 2;

                if (counter % 2 == 0)
                    resultArray[i] = (temp[val] + temp[val - 1]) / 2.0;
                else 
                    resultArray[i] = temp[val];
            }
        }
        System.out.println("\n Result Array : " + Arrays.toString(resultArray));
        return resultArray;
    }

    private static final Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) throws IOException {
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("d://output.txt"));

        int aCount = Integer.parseInt(scanner.nextLine().trim());

        int[] a = new int[aCount];

        for (int aItr = 0; aItr < aCount; aItr++) {
            int aItem = Integer.parseInt(scanner.nextLine().trim());
            a[aItr] = aItem;
        }

        double[] result = runningMedian(a);

        for (int resultItr = 0; resultItr < result.length; resultItr++) {
            bufferedWriter.write(String.valueOf(result[resultItr]));

            if (resultItr != result.length - 1) {
                bufferedWriter.write("\n");
            }
        }

        bufferedWriter.newLine();

        bufferedWriter.close();
    }
}

输入:

6
12
4
5
3
8
7

输出:

Result Array : [12.0, 8.0, 5.0, 4.5, 5.0, 6.0]