Algorithm 采访街道中央分隔带挑战赛

Algorithm 采访街道中央分隔带挑战赛,algorithm,median,Algorithm,Median,问题 M个数的中位数定义为 1) 如果M是按顺序排序后的奇数中间数 2) 如果M是中间2个数字的平均数(排序后再次) 首先,您有一个空的号码列表。然后您可以从列表中添加或删除一些数字。对于每个添加或删除操作,输出列表中数字的中位数 例如:对于一组m=5的数字,{9,2,8,4,1}中位数是排序集{1,2,4,8,9}中的第三个数字,即4。类似地,对于m=4,{5,2,10,4}的集合,中值是排序集合{2,4,5,10}中第二个和第三个元素的平均值,即(4+5)/2=4.5 我的方法 我认为这个问

问题 M个数的中位数定义为 1) 如果M是按顺序排序后的奇数中间数 2) 如果M是中间2个数字的平均数(排序后再次) 首先,您有一个空的号码列表。然后您可以从列表中添加或删除一些数字。对于每个添加或删除操作,输出列表中数字的中位数

例如:对于一组m=5的数字,{9,2,8,4,1}中位数是排序集{1,2,4,8,9}中的第三个数字,即4。类似地,对于m=4,{5,2,10,4}的集合,中值是排序集合{2,4,5,10}中第二个和第三个元素的平均值,即(4+5)/2=4.5

我的方法 我认为这个问题可以用这种方法解决。。 其思想是使用以前的中值和指针来查找新的中值,而不是在每次添加或删除操作时重新计算

1) 使用始终保持图元有序并允许重复的多重集。换句话说,以某种方式维护已排序的列表

2) 如果操作是“添加”

2.1) Insert this element into set and then calculate the median

2.2) if the size of set is 1 then first element will be the median

2.3) if the size of set is even, then

           if new element is larger then prev median, new median will be avg of prev median

               and the next element in set.

           else new median will be avg of prev median and previous of prev element in the set.

2.4) if the size is odd, then

          if new element is larger then prev median

                 if also less then 2nd element of prev median ( 2nd element used to calculate avg

                    of prev median) then this new element to be added will be new median

                 else median will be 2nd element use to calculate the avg during last iteration prev

                    median.

          else

                 new median will be previous of prev median element in the set
3) 如果该操作被取消,请删除

3.1) First calculate the new median

3.2) If the size of set is 0 can't remove

3.3) If the size is 1 if the first element is the element to be removed, remove it else can't remove.

3.4) If the size of set is even, then

           if the element to be deleted is greater than or equal to 2nd element of prev median, then

               1st element of prev median will be new median

          else 2nd element of prev median will be the new median

3.5) If the size of set is odd, then

           if the element to be deleted is the prev median then find the avg of its prev and  next element.

           else if the element to be deleted is greater then prev median, new median will be avg of prev median and previous to prev median

           else median will be avg of prev median and next element to prev median.

3.6) Remove the element. 

这是工作代码。。。。您对这种方法有何看法?

如果您的列表已排序,那么您可以使用类似于以下伪代码的方法在固定时间内计算中值

if list.length % 2 == 0 
   median = (list[list.length/2 - 1] + list[list.length/2]) / 2 
else
   median = list[list.length/2]
因此,只需在每次插入/删除时维护一个排序列表。您可以在
O(n)
时间内执行这些操作,方法是单步遍历列表,直到您位于元素和>=added element元素之间。你可以在 o(log n)时间内完成这些插入/移除,如果你从列表中间开始,然后决定你的元素是否小于或大于中间元素。取一半的列表,从中间开始重复。 您的问题没有说明这方面的性能要求,但就我所知,整个过程不可能总是在固定时间内发生。此实现具有以下性能

Insert    O(log n)
Remove    O(log n)
Median    O(1)

你的方法似乎可行,但从描述和代码中,你可以看出其中涉及到很多案例。我不想成为那个必须调试它的人!所以,让我给你们一个替代的解决方案,它应该涉及较少的案例,因此更容易得到正确的答案

保留两个多重集(此算法也适用于两个优先级队列,因为我们只看每个队列的极值)。第一个,
minset
,将保留最小的n/2个数字,第二个,
maxset
,将存储最后的n/2个数字

无论何时添加数字:

  • 如果大于
    max(minset)
    ,则将其添加到
    maxset
  • 否则,将其添加到
    minset
请注意,这并不保证n/2条件。因此,我们应该增加一个额外的“修复”步骤:

  • 如果
    maxset.size()
  • 如果
    minset.size()>minset.size()+1
    ,则从
    minset
    中删除最大的元素并将其插入
    maxset
完成后,我们只需要得到中间值。这在我们的数据结构中应该很容易做到:取决于当前n是偶数还是奇数,它要么是
max(minset)
,要么是
max(minset)
min(maxset)
之间的平均值


对于删除操作,只需尝试将其从任何集合中删除,然后再进行修复。

代码的主要问题是将每个新项目与运行的中位数进行比较,这可能是计算出的平均值。相反,您应该将新项目与上一中间的值进行比较(代码中的
*prev
)。也就是说,在接收到1和5的序列后,中值将是3。如果下一个值是2或4,它应该成为新的中位数,但由于您的代码对每一个中位数都遵循不同的路径,因此其中一个结果是错误的

总体而言,只跟踪中间位置而不是运行中间带会更简单。而是在每次添加/删除操作结束时计算中值:

if size == 0
    median = NaN
else if size is odd
    median = *prev
else
    median = (*prev + *(prev-1)) / 2

我认为您可以尝试验证两个案例:

1) negative number
4
a -1
a 0
a 0
r 0

2) two big integer whose sum will exceed max int

此代码解决了interviewStreet上的中值挑战

# this code solves the median challenge on interviewStreet.
# logic is simple. insert the numbers into a sorted sequence in place.
# use bisection to find the insert index(O(logn)). keep a count of no. of elements in
# the list and print the median using it(O(1)).
!/bin/python
from bisect import bisect_left
List = [] 
nnode = 0 

def printMed():
if nnode>0:
    if nnode%2 == 0 :
    if (0.5*(List[nnode/2]+List[(nnode/2)-1])).is_integer():
        print int(0.5*(List[nnode/2]+List[(nnode/2)-1]))
    else:
        print 0.5*(List[nnode/2]+List[(nnode/2)-1])
    else:
    print List[nnode/2]
else:
    print "Wrong!"

def rem(val):
global nnode
try:
        List.remove(val)
except:
    print "Wrong!"
else:
    nnode = nnode-1
    printMed()

if __name__ == "__main__":
    n = int(raw_input())
for i in range(0,n):
    l = raw_input().split()
    if(l[0] == 'r'):
        rem(int(l[1]))
    else:
    index = bisect_left(List , int(l[1])) ;
    List.insert(index ,int(l[1]))
    nnode = nnode+1 
    printMed() 

这是使用collections.sort(list)在java中解决中值挑战的解决方案

import java.util.*;
公共类解决方案{
ArrayList sortedList=新建ArrayList();
公共静态void main(字符串参数[]){
SolutionMedian m=新的SolutionMedian();
扫描仪输入=新扫描仪(系统输入);
int n=in.nextInt();
char[]op=新字符[n];
int[]val=新的int[n];

例如(int i=0;i当我删除中间值时,您的代码正在做一些奇怪的事情,例如:“4a1a1a1r1”谢谢ffao..这是一个小错误,现在已更正。但仍有一些问题我找不到…%g行为不正常请尝试使用更大的中值和x值,它将以科学符号打印在排序数据结构中,插入/删除是一个日志(n)操作。新的中间值将在旧中间值的附近,并且是一个常数时间操作;您需要检查一些情况。@vsaxena right..这就是我试图做的,但不确定我的方法是否正确插入和删除的最佳解决方案都是O(logn),同时保持O(1)对于中值运算,我使用C++中的多个集合,其中插入和删除发生在O(log n)中,求取中值取O(1)。使用我说的方法。您的逻辑不正确。如果长度%2==0,则列表的长度为偶数。将其更改为!=则正确。此外,您使用的是长度/2,它被向下截断,这是正确的。但是,您的长度/2-1被向下截断并降低1。它应该是长度/2+1。如果
import java.util.*;
public class SolutionMedian{
    ArrayList<Integer> sortedList = new ArrayList<Integer>();

    public static void main(String args[]){

        SolutionMedian m = new SolutionMedian();

        Scanner in = new Scanner(System.in);
        int n = in.nextInt();

        char[] op = new char[n];
        int[] val = new int[n];
        for(int i=0; i<n; i++){
            op[i] = in.next().charAt(0);
            val[i] = in.nextInt();
        }

        for(int i=0; i<n; i++)
            if(op[i] == 'a') 
                m.add(val[i]);
            else 
                m.remove(val[i]);
    }

void add(int val){
        sortedList.add(val);
        getMedian();
    }

    void remove(int val){
        int index = sortedList.indexOf(val);
        if(index>=0){
            sortedList.remove(index);
            getMedian();
        }else{ 
            System.out.println("Wrong!");
        }
    }

    void getMedian(){
        Collections.sort(sortedList);
        int size = sortedList.size();
        switch(size){
            case 0: 
                System.out.println("Wrong!");
                break;
            case 1: 
                System.out.println(sortedList.get(0));
                break;
            default: 
                if(size%2 == 0) {//even size
                    int halfIndex = size/2;
                    long sum = sortedList.get(halfIndex)
                              + sortedList.get(halfIndex-1);
                    if(1==(sum&1)) 
                        System.out.println((sum/2)+".5");
                    else 
                        System.out.println(sum/2);
                }else{//odd size
                    System.out.println(sortedList.get((size-1)/2));
                }
        }
    }
}