分析:容易想到不用排序,直接用一个数组记录每个数字出现次数即可。
时间:O(N+M),N为数据个数,M为最大数,为了简便直接定为30000;
空间:O(M)
代码:
分析:存数组里,快排。
时间:平均O(Nlg N+K)
空间:O(N)
代码:
分析:根据点到直线距离最短,在最短方案中,所有的连线必是垂直于管道的,即为南北方向。因此给出的x坐标没有作用。
现在,问题转化为:
已知n个数y1,y2,...,yn,求一个数y0,使得 |y1-y0|+|y2-y0|+...+|yn-y0|的值最小。
首先对y数组排序,不妨认为之后y1<=y2<=y3<=...<=yn。
若n为偶数,可将这些数分为n/2组:{y1,yn},{y2,y(n-1)},...,{y(n/2),y(n+1-n/2)};
对{y1,yn},易证当y1<=y0<=yn时,有|y1-y0|+|yn-y0|=yn-y1,若y0在此区域之外,则|y1-y0|+|yn-y0|>yn-y1。
此式对任意一组均成立,最终得出当y(n/2)<=y0<=y(n/2+1)时总和最小。为了程序简便,可以取二者平均数,即原数据的中位数。
若n为奇数,则分出n/2组后,还剩余一个数y(n/2+1),显然令y0=y(n/2+1)即可,仍然是求中位数。
综上,先将y数组排序,然后求中位数,根据要求输出距离之和。
时间复杂度:O(Nlg N)
空间复杂度:O(N)
代码:
分析:N值很大,直接存下来每个人的票数不可能。注意最多只有10000票,所以真正得到票的也不会超过10000人,这样就好办了。
一种方案是离散化(这个词有些高端,不过很简单),把存储的数组做成记录类型,两个域分别是编号和得票数。不过这样的话,每读入一个数,都要花O(M)的时间(或把记录的数组按编号排序,然后二分,这样也不会快多少)找到所在的位置,然后再处理,时间复杂度为O(M2),有可能超时。
另一种方案是把读入的数据排序,这样相同的编号必然在一起。然后可以在O(N)时间内扫描一遍,得到给有编号及他们出现的次数。这里是不用存储的,找到过半的输出,并立刻结束程序(显然不会有两个过半的)。
时间复杂度:O(Mlg M)
空间复杂度:O(M)
代码: