精华内容
下载资源
问答
  • 算法,求1亿数的中位数

    千次阅读 2013-10-11 14:36:17
    可以借鉴一下以下方法的: 有1亿浮点数,请找出其中最大的10000。提示:假设每浮点数占4字节,1亿浮点数就要站到相当大的空间,因此不能次将全部读入内存进行... 方法1: 读出100w数据, 找出最大

    http://bbs.csdn.net/topics/310150772

    可以借鉴一下以下方法的:

    有1亿个浮点数,请找出其中最大的10000个。提示:假设每个浮点数占4个字节,1亿个浮点数就要站到相当大的空间,因此不能一次将全部读入内存进行排序。

      ~~~~~~~~~~~~~

      既然不可以一次读入内存, 那可以这么试试:

      方法1: 读出100w个数据, 找出最大的1w个, 如果这100w数据选择够理想, 那么以这1w个数据里面最小的为基准, 可以过滤掉1亿数据里面99%的数据, 最后就再一次在剩下的100w(1%)里面找出最大的1w个咯~~

      方法2: 分块, 比如100w一个块, 找出最大1w个, 一次下来就剩下100w数据需要找出1w个了.(注意消重,这剩下的100w个数据应该是互不相同的。即每找出一个块里最大的1w个,就应该hash存储。下一个块中若出现了已存储的数据,则不计在此块的top 1w里,这样才能保证最终剩下的100w里面寻找top 1w就接近1亿里面的top 1w。想想:如果每个块的top 1w都基本是重复的,不消重的话,最终的结果有可能就少于1w个。)

      对于上面提到的找出100w个数据里面最大的1w个, 说起来比较罗嗦, 还是说说找到第1w个大的数字的方法:

      用快速排序的方法, 分2堆, 如果大的那堆个数N大于1w个, 继续对大堆快速排序一次分成2堆, 如果大堆个数N小于1w, 就在小的那堆里面快速排序一次, 找第10000-N大的数字; 递归以上过程, 就可以找到第1w大的数. 据说也是STL的search_n()的方法;(更好的一种类似的方法是将这些数以5个为一组,每组通过插入排序找出其中位数,再找出其中位数的中位数,依次递归,找出最终一个中位数x,然后按照x对序列进行快排,且设x是序列的第k大的数,如果要找的是第i大的数,则比较k与i的关系,如果相等,直接返回x,否则如果k>i,则在小的那堆里面继续按照这种方式快排,如果k<i,则在大堆里面找第i-k大的数。)

      参考上面的找出第1w大数字, 相信楼主就可以类似的方法找出前1w大数字了

     

    真的很感谢有这么多人回答,我的思路就是基本上排序+分块,
    首先1亿个数我分成了200块,每块50W个,对每个块进行多路归并排序(这里不考虑快速排序,相对来说比较低率,不稳定),
    排序好后存储在硬盘文件。
    我写了下,大约是15S左右,
    然后在用一个两维数组记录这200组数据中的最大和最小值,然后把这200个中位数的平均数求出来,其实没有别的目的
    (目的是为了找一个适合的中位数偏移点,因为这个平均数不一定就是1亿个数的,可以叫做先猜一个机率最大的吧)
    如果我们这么时候求得的平均数是N
    然后就是一个超级土的试探法了,
    建立一个偏差数组left[5][200],right[5][200],主要是用来保存N这个数在每个块里面小于N和大于N 5个的数,用来在后面读取
    1。从文件里一个一个读取排序好的块,顺便把left,right两数组填充,找出<=N的数所在的index,最后把这些index相加为sum,看sum是否==1亿/2-1
    如果相等了,那证明这个数就是中位数了,
    2.如果小于
    就又从left[0][200]里取最大的一个值,把left[0]排序一下,这样肯定是最接近N的,然后重复1,但是不改变left,right,看是否是中位数,
    如果sum继续小于,那么继续2,但是要取left[1][200]最大了,如果sum这时候大于了,证明中位数肯定存在于left[0][200]其中的一个了,
    这时候就锁定了,在left[0]用折半找按上面方法计算sum找中位数,
    3。如果大于,和2步骤就是相反的。

    这个算法虽然可以找到相关的值,但是在从文件重复读块加载到内存方面不知道读取了多少次,效率肯定不是一般的差,想了一两天,没思路了,哎。

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    内存只能容纳100W个数,
    现在有1亿数,混序,
    然后求这一亿个数的中位数,
    中位数(就是一个有序数组的中间数字,数组长度为偶数就是两个,奇数则只有一个)
      
    /*****************************************************************************/
    /* this program should find out the median(s) in N(logN)/(logB) no matter there
    /* is duplicated data or not.
    /*
    /* with memory limitation: 4MB memory available.
    /* I would like to express the idea with code.
    /* here is just the pseudocode with out any optimization for easy understanding.
    /* 
    /* maybe, there is no need to check sum == N/2 or N/2+1, but this will get the 
    /* median(s) as soon as possible with out more recursive invoking.
    /*
    /* sorry for any logical problem. please let me know if you found any.
    /*****************************************************************************/
      
      
    int N = 100000000;// total data number is N
    int B = 1000000;  // number of buckets.
    int min, max;
    scan data from 0 to N-1 get min and max; // O(N);
      
    void find_median(int num=0, int min, int max)
    {
        if(min == max) {
            if(N%2) {
                print medians are min and max;
            }
            else print median is min; // show you the result
            return// exit
        }
      
        /* count all the data in O(N)*/
        int m = max-min > B ? (max-min) / B : 1;
        int cnt[B] = {0}; // count the data read.
        while(!EOF) {
            int data = read_data()-min;
            if(data >= min && data <= max) cnt[data/m]++;
        }
          
        int sum = num, median_1, median_2, i = 0;
        while(sum < N/2) sum += cnt[i++];
        i--; // median is in the range of [i*m, (i+1)*m-1]
      
        /* get median(s) when sum is N/2 */
        if(sum == N/2) {
            if(N%2) { // N is even and there are two medians.
                median_1 = (i+2)*m-1;
                median_2 = i*m;
                while(!EOF) {
                    int data = read_data()-min;
                    if(data/m == i) {
                        median_2 = (data > median_2 ? data : median_2);
                    }
                    if(data/m == i+1) {
                        median_1 = (data < median_1 ? data : median_1);
                    }
                }
                pintf medians are median_1 and median_2;
                return;
            }
        }
        else // N is an odd number and there is one median.
            median_1 = (i+2)*m-1;
            while(!EOF) {
                int data = read_data();
                if(data/m == i+1) median_1 = (data < median_1 ? data : median_1);
            }
            print median is median_1;
            return;
        }
          
        /* get median(s) when sum is N/2+1 */
        if(sum == N/2+1) {
            if(N%2) { // N is even and there are two medians.
                median_1 = i*m;
                median_2 = i*m;
                while(!EOF) {
                    int data = read_data();
                    if(data/m == i) {
                        median_1 = max;
                        median_2 = (data > median_2 ? data : median_2);
                    }
                }
                pintf medians are median_1 and median_2;
                return;
            }
        }
        else {
            median_2 = i*m; // get (N/2+1)th data.
            while(!EOF) {
                int data = read_data();
                if(data/m == i) median_2 = (data > median_2 ? data : median_2);
            }
            print median is median_2;
            return;
        }
      
        /* recursively to find out the median(s) */
        min = (i+1)*m-1;
        max = i*m;
        // get min and max for next processing
        while(!EOF) 
        {
            int data = read_data()-min;
            if(data/m == i)
            {
                min = (data < min ? data : min);
                max = (data > max ? data : max);
            }
        }
        find_median(sum, min, max);
    }
    展开全文
  • 数据流中的中位数

    千次阅读 2018-07-02 11:28:58
    题目描述 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。由于...

    题目描述

            如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。

    由于数据是从一个数据流中读出来,因而数据的数目随着时间的增加而增加,如果用一个数据容器来保存从流中读出来的数据,则当新的数据从流中读出来的时候,这些数据就插入数据容器。这个数据用什么数据结构定义合适呢?接下来讨论一下最合适的数据结构:

    首先,先用一个表格列出可用数据结构的各复杂度

     

    不同数据结构的时间复杂度
    数据结构 插入的时间复杂度 得到中位数的时间复杂度
    没有排序的数组 O(1) O(n)
    排序的数组 O(n) O(1)
    排序的链表 O(n) O(1)
    二叉搜索树 平均O(logN),最差O(n) 平均O(logN),最差O(n)
    VAL树 O(logN) O(1)
    最大堆和最小堆 O(logN) O(1)

    接下来,细细分析一下:

     

    1. 数组是最简单的数据容器。如果数组没有排序,那么可以用前面提到的Partition函数找出数组中的中位数。在没有排序的数组中插入一个数字和找出中位数的时间复杂度分别是O(1)和O(n)。
    2. 在往数组里插入数字的时候我们可以让数组保持排序。这时由于可能需要移动O(n)个数字,因此需要O(n)的时间复杂度。在已排好的数组中取中位数,我们只需要O(1)的时间复杂度即可。
    3. 排序的链表是另外一种选择,我们需要O(n)的时间复杂度才能在链表中找到其合适的位置插入新的数据。如果定义两个指针指向链表中间的节点,那么可以在O(1)的时间内得出中位数。
    4. 二叉搜索树可以把插入新数据的平均时间复杂度降低到最低,但是由于二叉搜索树极度不平衡,从而看起来像一个排序的链表的时候,插入新数据的时间仍然是O(n),为了得到中位数,可以在二叉树节点中添加一个表示子树节点数目的字段。有了这个字段,可以在平均O(logN)时间内得到中位数,但最差情况仍然是O(logN)。
    5. 为了避免二叉搜索树的最差情况,可以利用平衡的二叉搜索树,即VAL树。通常VAL树的平衡因子是左右子树的高度差。可以稍作修改,把VAL树的平衡因子改为左右子树节点数目之差。有了这个改动,可以用O(logN)时间往VAL树中添加一个新节点,同时用O(1)时间得到所有节点的中位数。
    6. 虽然VAL树的效率很高,但是大部分编程语言的函数库是没有实现这个数据结构的,在面试期间短短几十分钟也是不可能实现这个功能的,所以只能考虑其他办法。

     

    从上图可以看到,如果容器中数据的数目是奇数,那么两个指针指向同一个数据。

    我们可以发现,整个数据容器被分成两个部分。位于容器左边部分的数据结构比右边的数据结构小。另外,p1指针指向的数据是左边部分最大的数,p2指向的是右边部分最小的数。

     

            OK,找出最优的数据结构后,我们再考虑一点细节。首先要保证数据平均分配到两个堆中,因此两个堆中的数据的数目之差不能为1。为了实现平均分配,可以在数据的总数目是偶数的情况下把新数据插入最小堆,否则插入最大堆。

            还要保证最大堆的所有数都大于最小堆,因此按照前面的分配规则,会把新的数据插入最小堆。如果此时插入最小堆的数据大于最大堆的最小值,那么它就不能成为最小堆的数据,因此我们需要把这个新数据先插入最大堆,然后取出最大堆里最小值min,再把找到min插入最小堆中,以此来满足我们的规则——最小堆中所有数字都小于最大堆的数字。同理可插入新数据进入最大堆。

    以下为C#实现的代码,用两个list作为堆容器来实现的:

    
    using System;
    using System.Collections.Generic;
    
    namespace 数据流中的中位数
    {
        class Program
        {
            static void Main(string[] args)
            {
                int[] num = new int[9] { 5, 2, 3, 4, 1, 6, 7, 0, 8 };
                Solution s = new Solution();
                for (int i = 0; i < num.Length; i++)        //模拟逐次从流中读出数据,取其中位数查看结果
                {
                    s.Insert(num[i]);
                    Console.WriteLine(s.GetMedian());
                }
            }
        }
        class Solution
        {
            private List<int> max = new List<int>();                //容器右边较大数所存储的堆
            private List<int> min = new List<int>();                //容器左边较小数所存储的堆
    
    
            /// <summary>
            /// 首先需要保证最大堆和最小堆能够平均分配数据,因此两个堆的数目差不能超过1.为了实现平均分配,可以在数据的总数目是偶数时把新数据插入最小堆,否则插入最大堆。
            /// </summary>
            /// <param name="num">插入的数字</param>
            public void Insert(int num)
            {
                //如果两个容器数量不平衡,则让其保持平衡,把新数据添加到max中
                if (((min.Count + max.Count) & 1) == 0)
                {
                    //新插入的数据大于最小堆的最大值,那么先把这个数据添加进最大堆,然后取出最大堆的最小值,把最小值插入最小堆min中
                    if (max.Count > 0 && num > max[0])
                    {
                        Add(max, num);
                        num = max[0];
                        max.RemoveAt(0);
                    }
                    Add(min, num);
                }
                else
                {
                    //如果要把新数据插入最大堆max,先判断新数据是否小于最小堆的最大值,如果是,那么先把新数据插入最小堆,取出最小堆的最大值,
                    //把得到的最大值插入最大堆max中
                    if (min.Count > 0 && min[min.Count - 1] > num)
                    {
                        Add(min, num);
                        num = min[min.Count - 1];
                        min.RemoveAt(min.Count - 1);
                    }
                    Add(max, num);
                }
            }
    
    
            /// <summary>
            /// 用来得到中位数,如果最大堆和最小堆的数量加起来是偶数,说明中位数得计算,那么求最大堆最小值与最小堆最大值的和的一半即可
            /// </summary>
            /// <returns>中位数</returns>
            public double GetMedian()
            {
                int size = min.Count + max.Count;
                //如果两个堆数据数目之和为奇数,说明返回最小堆的最大值即可(因为优先插入最小堆,最小堆会比最大堆多一个数)
                if ((size & 1) == 0)
                    return (double)(min[min.Count - 1] + max[0]) / 2.0;
    
    
                return (double)min[min.Count - 1];
            }
    
    
            //排好序的添加到两个堆中,都按升序排列,在调用最小堆时,则逆序调用即可
            private void Add(List<int> list, int num)
            {
                if (list.Count == 0)
                    list.Add(num);
                else
                {
                    for (int i = 0; i < list.Count; i++)
                    {
                        if (list[i] > num)
                        {
                            list.Insert(i, num);
                            return;
                        }
                    }
                    list.Add(num);
                }
            }
        }
    }

     

    展开全文
  • 剑指OfferJZ63:数据流中的中位数jz63:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序...

    jz63:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

    采用大顶堆和小顶堆分别维护中位数的左边区间的数和右边区间的数

    如果数据流有偶数个数值,那么中位数为(左区间的最大值+右区间的最小值)/2
    如果数据流有奇数个数值,那么中位数为(左区间的最大值 | 右区间的最小值)(这个可以自定义,哪个区间多一个数就取哪个区间)
    那么采用堆:
    取左区间的最大值就相当于取大顶堆的堆顶
    取右区间的最大值就相当于取小顶堆的堆顶

    import java.util.PriorityQueue;
    public class Solution {
    //设置两个优先队列(队列:先进先出;优先级队列中,数据按关键词有序排列,插入新数据的时候,会自动插入到合适的位置保证队列有序,默认排序为升序)
        private PriorityQueue<Integer> queue1=new PriorityQueue<>(((o1,o2)->(o2-o1)));//构造大顶堆:中位数的左区间
        private PriorityQueue<Integer> queue2=new PriorityQueue<>();//构造小顶堆:中位数的右区间(优先队列默认构造的是小堆顶,因为每次取出的队顶元素都是最小的,所以也可以new PriorityQueue<>(((o1,o2)->(o1-o2)));)
        private int sum=0;//标记数据流中个数
    
    
        public void Insert(Integer num) {
            //读取数据流
            if(sum%2==0){
                //当两个堆的元素个数一样时,此时新增一个元素,放入大顶堆(左区间)(这样自定义:到时候中位数就取大顶堆堆顶)
                queue1.add(num);//大顶堆
            }else{
                queue2.add(num);//小顶堆
            }
            //如果出现大顶堆的堆顶大于小顶堆的堆顶的情况,就将两堆顶互换位置
            if(!queue2.isEmpty() && queue1.peek()>queue2.peek()){
                //peek:查询队顶元素
                // poll:删除一个元素,并返回删除的元素
                assert !queue1.isEmpty();//设置assert !queue1.isEmpty();和!queue2.isEmpty()防止空指针报异常
                int temp1=queue1.poll();
                int temp2=queue2.poll();
                queue1.add(temp2);
                queue2.add(temp1);
            }
            sum++;
        }
    
        public Double GetMedian() {
            //获取当前读取数据的中位数
            if(sum%2==1){
                //是奇数,中位数为:大顶堆堆顶
                return (double)queue1.peek();
            }else{
                //是偶数,中位数为:(大顶堆堆顶+小顶堆堆顶)/2
                return (double)(queue1.peek()+queue2.peek())/2.0;
            }
        }
    }
    

    在这里插入图片描述

    展开全文
  • 剑指Offer--064-数据流中的中位数

    千次阅读 2016-07-14 12:44:39
    牛客OJ:数据流之中的中位数 九度OJ:未收录 GitHub代码: 064-数据流之中的中位数 > CSDN题解:剑指Offer–064-数据流之中的中位数 | 牛客OJ | 九度OJ | CSDN题解 | GitHub代码 | | ————- |:————-:...

    1 链接


    牛客OJ:数据流之中的中位数

    九度OJ:未收录

    GitHub代码: 064-数据流之中的中位数

    CSDN题解:剑指Offer–064-数据流之中的中位数

    牛客OJ 九度OJ CSDN题解 GitHub代码
    064-数据流之中的中位数 未收录 剑指Offer–064-数据流之中的中位数 064-数据流之中的中位数

    2 题意


    题目描述

    如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。

    3 分析


    数据结构 插入的时间效率 得到的中位数的时间效率
    没有排序的数组 O(1) O(n)
    排序的数组 O(n) O(1)
    排序的链表 O(n) O(1)
    二叉搜索树 平均O(logn), 最差O(n) 平均O(logn), 最差O(n)
    AVL树 O(logn) O(1)
    最大堆和最小堆 O(logn) O(1)

    4 堆排序策略


    对于数据流,对应的就是在线算法了,一道很经典的题目就是在1亿个数中找到最大的前100个数,这是一道堆应用题,找最大的前100个数,那么我们就创建一个大小为100的最小化堆,每来一个元素就与堆顶元素比较,因为堆顶元素是目前前100大数中的最小数,前来的元素如果比该元素大,那么就把原来的堆顶替换掉。

    那么对于这一道题呢?如果单纯的把所有元素放到一个数组里,每次查找中位数最快也要O(n),综合下来是O(n^2)的复杂度。我们可以利用上面例子中的想法,用一个最大堆来维护当前前n/2小的元素,那么每次找中位数只到取出堆顶就可以了。但是,有一个问题,数据要动态增长,有可能之前被替换掉的元素随着元素的增加又跑回来了,所以我们不能单纯得向上题一样把元素丢掉,我们可以再用一个最小化堆来存前n/2大的元素。

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    
    
    //  调试开关
    #define __tmain main
    
    #ifdef __tmain
    
    #define debug cout
    
    #else
    
    #define debug 0 && cout
    
    #endif // __tmain
    
    
    
    class Solution
    {
    protected:
        vector<int>     m_min; //数组中的后一半元素组成一个最小化堆
        vector<int>     m_max; //数组中的前一半元素组成一个最大化堆
    
    public:
        /*  将元素插入的堆中, 
         *  为了保证数据平均的分配到两个堆中, 两个堆的数据数目之差不能超过1
         *  插入的元素会两个堆元素的平衡, 因此两个堆都必须调整
         *
         *  比如将元素插在后半段(最小堆)中,
         *  则最小堆调整后的堆顶(最小值)需要弹出并压入到前半段中才能保证平衡
         * 也就是说, 在最小堆中插入元素, 最后完成调整后将导致最大堆中元素+1
         *
         *  因此我们可以假定, 0 <= m_min.size( ) - m_max.size( ) <= 1
         *  那么
         *
         *  插入前如果整个数组的元素个数为偶数, 说明两个堆中元素个数相等
         *  则最终元素应该插入m_min中,即先把元素插入到m_max中在调整到m_min中
         *
         *  插入前如果整个数组的元素个数为奇数, 说明m_max元素多了1个
         *  则最终元素应该插入m_max中,
         *  即先把元素插入到m_min中在调整到m_max中
         *  */
        void Insert(int num)
        {
            if(((m_min.size( ) + m_max.size( )) & 1) == 0)
            {
                /*  偶数数据的情况下
                 *  直接将新的数据插入到数组的后半段
                 *  即在最小堆中插入元素
                 *
                 *  此时最小堆中多出一个元素,
                 *  即最小元素, 将其弹出后, 压入前半段(即最大堆中)
                 *  */
                if(m_max.size( ) > 0 && num < m_max[0])
                {
                    m_max.push_back(num);
                    push_heap(m_max.begin( ), m_max.end( ), less<int>( ));
    
                    num = m_max[0];
                    pop_heap(m_max.begin(), m_max.end(), less<int>());
                    m_max.pop_back();
                }
                m_min.push_back(num); //把前一半找到的最大值放到后一半中
                push_heap(m_min.begin( ), m_min.end( ), greater<int>( ));
                debug <<"left = " <<m_max.size( ) <<", " <<m_min.size( ) <<endl;
            }
            else
            {
                /*  否则数组中元素是奇数
                 *  将
                 *
                 * */
                if(m_min.size( ) > 0 && num > m_min[0])    //  奇数数据的情况下,则在最大堆中插入元素
                {
                    m_min.push_back(num);
                    push_heap(m_min.begin(), m_min.end(), greater<int>());
                    num=m_min[0];
                    pop_heap(m_min.begin(), m_min.end(), greater<int>());
                    m_min.pop_back();
                }
                m_max.push_back(num); //把后一半找到的最大值放到前一半中
                push_heap(m_max.begin(), m_max.end(), less<int>());
            }
        }
    
        /*  由于假定, 0 <= m_min.size( ) - m_max.size( ) <= 1
         *  因此
         *  当总元素个数为偶数时, 中位数即(m_max[0] + m_min[0]) / 2
         *  当总元素个数为奇数时, 中位数即m_min[0];  */
        double GetMedian()
        {
            int size = m_min.size( ) + m_max.size( );
            if(size==0) return -1;
            double median = 0;
            if((size & 1) != 0)
            {
                median = (double) m_min[0];
            }
            else
            {
                median = (double) (m_max[0] + m_min[0]) / 2;
            }
            return median;
        }
    };
    
    int __tmain( )
    {
        Solution s;
        int array[] = {5, 2, 3, 4, 1, 6, 7, 0, 8};
        vector<int> vec(array, array + 9);
    
        for (int i = 0; i < vec.size( ); i++)
        {
            s.Insert(vec[i]);
            cout << s.GetMedian( ) << endl;
        }
        return 0;
    }

    5 哈希set-multiset策略


    类似的策略, 我们可以采用multiset来实现, set和multiset会根据特定的排序准则,自动将元素进行排序。不同的是后者允许元素重复而前者不允许

    class Solution
    {
    protected :
        multiset<int>   left;       /*  左半部分  */
        multiset<int>   right;      /*  右半部分  */
    
    public    :
    
        void Insert(int n)
        {
            int tmp = n;
            if(((left.size( ) + right.size( )) & 1) == 0)
            {
                if (right.empty( ) != true && n > *right.begin())
                {
                    right.insert(n);
                    tmp = *right.begin( );
                    right.erase(right.find(tmp));
                }
                left.insert(tmp);
            }
            else
            {
                if (left.empty() != true && n < *left.rbegin())
                {
                    left.insert(n);
                    tmp = *left.rbegin();
                    left.erase(left.find(tmp));
                }
                right.insert(tmp);
            }
    
        }
    
        double GetMedian( )
        {
    #ifdef __tmain
            cout <<"left[" <<left.size( ) <<"] : ";
            copy(left.begin( ), left.end( ), ostream_iterator<int>(cout," "));
            cout <<"right[" <<right.size( ) <<"] : ";
            copy(right.begin( ), right.end( ), ostream_iterator<int>(cout," "));
            cout <<endl;
    #endif
    
            if(((left.size( ) + right.size( )) & 1) == 0)
            {
                debug <<*left.rbegin( ) <<", " <<*right.begin( ) <<endl;
                return (double)(*left.rbegin( ) + *right.begin( )) / 2.0;
            }
            else
            {
                debug <<(double)*left.rbegin( ) <<endl;
                return (double)*left.rbegin( );
            }
        }
    };
    展开全文
  • 郑州某信息技术有限公司是一个拥有200多位员工的软件开发公司,担任人事工作的丁女士每到月底都忙前忙后,愁云惨雾。后来她无意间尝试使用了超级表格,就再也没有离开它。 她说:“我最看中的就是超级表格的分享功能...
  • 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。 样例 输入:1...
  • 位数为0的时候,显示为空白。//用两个按键控制数值的加减,按一次K1数字加1,按一次K2数字减1,数值的范围是从0到99。//再用一个接近开关控制数字的减小,接近开关感应一次数字减1,减到0停止。// C语言程序如下。...
  • C语言操作

    千次阅读 多人点赞 2017-06-04 16:51:00
    1、注意:与符号是一个&,两个&&是逻辑与。 2、真值表:1&0=0 1&1=1 0&0=0 0&1=0 3、从真值表可以看出:与操作的特点是,只有1和1与结果为1,其余全是0. 4、与和逻辑与的区别:与时两个操作是按照二进制...
  • DS18B20读出85摄氏度

    千次阅读 2019-06-17 14:21:48
    关于DS18B20初始化时候读出85摄氏度的问题,我相信很朋友都遇到过。 很多人估计没有解决这问题。最后不得已的情况下读了几次,然后才开始显示。 问题就是因为,DS18B20默认是12采样,具体时间看下表: ...
  • 迷茫,仿佛就是一团乌云,笼罩在每一个心中怀有抱负的人的头上。每当夜深人静,思绪归于对自己人生未来的严肃思考,不知去往何处的苦闷,再加之不断迫近的升学/就业选择的压力,尤其是一些看似周密的计划,由于想把...
  • 操作码和操作罗列在一起的语法,就是一个英文的指令文本。操作码是动词,操作相当于宾语。例如,用汇编语言来分析“Give me money”这个英文指令的话,Give就是操作码,me和money就是操作。汇编语言中存在个...
  • poi导出的excel的数字小数过多

    千次阅读 2018-05-02 09:06:01
     最近在使用Apache的POI组件对Excel进行操作,在对excel导出的时候,导出的数字本来只有两位小数,得到的结果就变成了很多位小数。如下面的图所示: 虽然对单元格使用了setCellStyle,但还是治标不治本,显示虽然...
  • 如何制作一个简单的16CPU

    千次阅读 2012-11-16 09:58:56
    我果然标题党了吗?...如何制作一个简单的16CPU,首先我们要明确CPU是做什么的,想必各位都比我清楚,百度的资料也很全。。。。。 http://baike.baidu.com/view/2089.htm 如果想要制作一个
  • 笔者寄语:批量读取目前看到有以下几种方法:xlsx包、RODBC包、批量转化成csv后读入。 xlsx包 首先尝试用R包解决。...百度了一下,网上已有很解决方案。我主要是参考这帖子,操作步骤为: 1、 安装最新版本
  • 但由于IEEE754浮点数标准所固有的精度问题,给很的情况下对于浮点数的格式化显示问题带来了困难。以下是一些与浮点数相关的使用情境中所常见的问题: 1、数据库中存储的某双精度浮点数2.02,通过程序读出后表示为...
  • 在大四的时候曾经遇到过,在进行串口通讯时,只能通过8位数组,88的传输数据,因此有时需要读取或存储更高位的数据例如16或32时,就会存在数据的拆分和组合的问题。 当时的解决方法是通过定义共用体,或者...
  • LSB最低有效和MSB最高有效

    万次阅读 多人点赞 2016-04-18 09:55:29
    最低有效(the least significant bit,lsb)是指一个二进制数字中的第0(即最低),具有权值为2^0,可以用它来检测的奇偶性。与之相反的称之为最高有效。在大端序中,lsb指最右边的。 ...
  • FIFO读写侧位不同的处理

    千次阅读 2019-04-02 18:04:35
    显然,输入与输出不匹配,此时有两个方法可以进行拼接,一个方法是FIFO的位宽依旧为8Bit,在写侧进行数据的拼接,代码如下: //读侧设置一个计数器,读两次,输出一次 always@(posedge clk or ne...
  • 关于DS18B20初始化时候读出85摄氏度的问题,我相信很朋友都遇到过。 很多人估计没有解决这问题。最后不得已的情况下读了几次,然后才开始显示。 问题就是因为,DS18B20默认是12采样,具体时间看下表:...
  • 找最小的K个数

    千次阅读 多人点赞 2011-10-24 23:51:45
    今天在CSDN无意中看到July一篇号称《当今世界最为经典的十大算法》的博文,感觉这文章名字挺霸气,于是进去瞅了一眼。...文章是以这样一个问题开始的:如何在一堆数据中找出最小的K个。 随便想了一
  • 大数据经过10年发展,现在已经到了一个重要的分水岭阶段:通用性和兼容性能力成为大数据发展主流,运行的稳定可靠和使用的简捷、易开发、易维护成为产品发展的驱动力,而这正是 Hadoop/Spark 这类积木式模块框架无法...
  • 区块链:一个故事告诉你比特币的原理及运作机制

    万次阅读 多人点赞 2017-04-12 11:26:54
    一个故事告诉你比特币的原理及运作机制推荐:《人工智能:法国浪漫之都的人工智能时代》《 花非花,物非物,AI岂是池中物(人工智能篇)》《致我们的青春,一个敬礼》周末花时间看了一些比特币原理相关的资料,虽然不...
  • 随机生成100学生的成绩保存在文件scores.txt文件中; 1). 从文件中读出学生的成绩,输出最高、最低,以及平均成绩(平均成绩为小数)。 2). 从文件中读出学生的成绩,统计90分以上学生的人数并输出。 3). 求出这次...
  • 一代、二代、三代测序技术原理与比较

    万次阅读 多人点赞 2017-11-10 14:08:02
    从1977年第一代DNA测序技术(Sanger法)1,发展至今三十多年时间,测序技术已取得了相当大的发展,从第一代到第三代乃至第四代,测序读长从长到短...在这里我主要对当前的测序技术以及它们的测序原理做一个简单的小结。
  • 程序员必知的 89 操作系统核心概念

    万次阅读 多人点赞 2020-03-31 19:13:39
    操作系统(Operating System,OS):是管理计算机硬件...操作系统也提供一个让用户与系统交互的操作界面。 shell:它是一个程序,可从键盘获取命令并将其提供给操作系统以执行。 在过去,它是类似 Unix 的系统上...
  • ... 有关数字辨别的一个关键考点就是类似30/13,40/14,50/15,60/16的听音,看大家能否听出其发 音区别。听力理解中难以分辨的基数词主要有以下几对:  thirteen与thirty; fourteen与...
  • 虽然并不是真正意义上的“同一时间点”,而是个任务或进程共享一个CPU,并交由操作系统来完成任务间对CPU的运行切换,以使得每个任务都有机会获得一定的时间片运行。 随着任务对软件开发者带来的新挑战,程序...
  • 获取亿数据获取前100最大值

    万次阅读 2014-09-25 18:40:26
    获取亿数据获取前100最大值

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 59,086
精华内容 23,634
关键字:

怎样读出一个多位数