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