【问题标题】:Finding the running median寻找运行中位数
【发布时间】:2017-05-12 02:15:39
【问题描述】:

我必须根据这个问题找到运行中位数: 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);
    }
}

【问题讨论】:

  • 欢迎来到 Stack Overflow。请花时间阅读The Tour 并参考Help Center 中的材料,您可以在这里问什么以及如何问。
  • 调试器是解决此类问题的正确工具。 询问 Stack Overflow 之前,您应该逐行逐行检查您的代码。如需更多帮助,请阅读How to debug small programs (by Eric Lippert)。至少,您应该 [编辑] 您的问题以包含一个重现您的问题的 Minimal, Complete, and Verifiable 示例,以及您在调试器中所做的观察。
  • 如果两个堆之间的差异不超过 1,那么您只需要保留每个堆的一个元素。

标签: c++ algorithm heap median


【解决方案1】:

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

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

    }

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

【讨论】:

  • 我修复了错误但是在提交代码时我仍然得到错误的答案:(
【解决方案2】:

使用 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]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-31
    • 2018-05-17
    • 2012-08-11
    • 2012-07-06
    • 1970-01-01
    • 2012-05-26
    • 2011-11-04
    相关资源
    最近更新 更多