中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
例如,
[2,3,4] 的中位数是 3
[2,3] 的中位数是 (2 + 3) / 2 = 2.5
设计一个支持以下两种操作的数据结构:
void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。
来源:力扣(LeetCode)
#define MAX_SIZE 50001
typedef struct
{
int* stack1;
int top1;
int* stack2;
int top2;
double medNum;
} MedianFinder;
/** initialize your data structure here. */
MedianFinder* medianFinderCreate()
{
MedianFinder* obj = (MedianFinder*)malloc(sizeof(MedianFinder));
obj -> stack1 = (int*)malloc(sizeof(int) * MAX_SIZE);
obj -> top1 = -1;
obj -> stack2 = (int*)malloc(sizeof(int) * MAX_SIZE);
obj -> top2 = -1;
obj -> medNum = 0;
//printf("1 % 2 = %f\n", 1 % 2);
return obj;
}
void
medianFinderAddNum(MedianFinder* obj, int num)
{
if (obj -> top1 == -1&&obj -> top2 == -1)
{ //第一次添加元素
obj -> stack1[++ obj -> top1] = num;
obj -> medNum = num;
return;
}
else if (obj->top1 >= 0 && num < obj -> stack1[obj -> top1])
{ //比stack1的栈顶元素小
while (obj->top1 >= 0 && num < obj -> stack1[obj -> top1])
{
obj -> stack2[++ obj -> top2] = obj -> stack1[obj -> top1 --];
}
obj -> stack1[++ obj -> top1] = num;
}
else if (obj -> top1 >= 0&&num == obj -> stack1[obj -> top1])
{ //与stack1的栈顶元素相等
obj->stack1[++obj->top1] = num;
//obj->medNum = num;
}
else if (obj -> top1 >= 0&&num > obj -> stack1[obj -> top1])
{ //比stack1的栈顶元素大
if (obj -> top2 == -1)
{ //stack2无数据
obj -> stack1[++ obj -> top1] = num;
//obj->medNum = num;
} else { //stack2有数据
if(num <= obj -> stack2[obj->top2])
{ //比stack2的栈顶元素小或相等
obj -> stack1[++ ob j-> top1] = num;
//obj->medNum = num;
} else { //比stack2的栈顶元素大
while (obj -> top2 >= 0&&num > obj -> stack2[obj -> top2])
{
obj -> stack1[++ obj -> top1] = obj -> stack2[obj -> top2 --];
}
obj -> stack2[++ obj -> top2] = num;
}
}
}
int sum = obj->top1 + 1 + obj -> top2 + 1;
if (sum % 2 == 1)
{ //奇数个元素
int mid = sum / 2 + 1;
if (mid <= obj -> top1 + 1)
{
obj- > medNum = 1.0 * obj -> stack1[mid - 1];
}
else
{
obj -> medNum = 1.0 * obj -> stack2[obj->top2 + 1 - (mid - obj->top1 - 1)];
}
}
else
{ //偶数个元素
int mid1 = sum / 2;
int mid2 = sum / 2 + 1;
if (mid2 <= obj -> top1 + 1)
{
obj -> medNum = 1.0 * (obj -> stack1[mid1 - 1] + obj -> stack1[mid2 - 1]) / 2.0;
}
else if (mid1 <= obj->top1 + 1 && mid2 > obj->top1 + 1)
{
obj- > medNum = 1.0 * (obj -> stack1[mid1 - 1] + obj -> stack2[obj
-> top2 + 1 - (mid2 - obj->top1 - 1)]) / 2.0;
}
else if (mid1 > obj -> top1 + 1)
{
obj -> medNum = 1.0 * (obj -> stack2[obj -> top2 + 1 - (mid1 - obj -> top1 - 1)]
+ obj -> stack2[obj-> top2 + 1 - (mid2 - obj -> top1 - 1)]) / 2.0;
}
}
}
double
medianFinderFindMedian(MedianFinder* obj)
{
if (obj ->top1 == -1 && obj -> top2 == -1)
{
return 0;
}
return obj -> medNum;
}
void
medianFinderFree(MedianFinder* obj)
{
free(obj -> stack1);
free(obj -> stack2);
free(obj);
}
/**
* Your MedianFinder struct will be instantiated and called as such:
* MedianFinder* obj = medianFinderCreate();
* medianFinderAddNum(obj, num);
* double param_2 = medianFinderFindMedian(obj);
* medianFinderFree(obj);
*/