• 数组中超过出现次数一半的数字 【微软面试100题 第七十四题】


    问题要求:

      数组中有一个数字出现的次数超过了数组长度的一半,找出这个数字。

      参考资料:编程之美2.3 寻找发帖水王

    问题分析:

      方法1 对数组排序,然后顺次查找其中最多的;

      方法2 对数组排序,最中间一个肯定为要找的数字,时间复杂度O(NlogN);

      方法3 每次消去数组中两个不同的数,最后剩下的肯定为要找的数字,时间复杂度O(N).

      方法3代码1如下,以下是图解代码1

    代码实现:

    //代码1
    #include <stdio.h> int Find(int* ID, int N); int main(void) { int ID[30] = {1,2,3,4,1,1,2,1,1,1,12,1}; printf("水王id: %d ",Find(ID,12)); return 0; } int Find(int* ID, int N) { int candidate; int nTimes, i; for(i = nTimes = 0; i < N; i++) { if(nTimes == 0) { candidate = ID[i], nTimes = 1; } else { if(candidate == ID[i]) nTimes++; else nTimes--; } } return candidate; }

    扩展问题1:

      如果改为该数字长度为数组长度的一半,又该如何求?

    问题分析:

      先消掉3个不同的id,再使用代码1的方法求解。因为消除3个不同id时,水王id最多消除一个,则,这样之后水王id个数就大于总数的一半了,就变成原问题了。

    代码实现:

      

    #include <stdio.h>
    
    int Find(int* ID, int N);
    
    int main(void)
    {
        int ID[6] = {2,1,2,1,3,1};
        printf("水王id: %d
    ",Find(ID,6));
        return 0;
    }
    int Find(int* ID, int N)
    {
        int candidate;
        int nTimes = 0, i;
        int flag = 0;
        int del[3];
        del[0] = ID[0];
        for(i = 1; i < N; i++)
        {
            if((ID[i] != del[0]) && (flag == 0))
            {
                del[1] = ID[i];
                flag = 1;
                continue;
            }
            if((ID[i] != del[0]) && (ID[i] != del[1]) && (flag == 1))
            {
                flag = 2;
                continue;
            }
            if(nTimes == 0)
            {
                 candidate = ID[i], nTimes = 1;
            }
            else
            {
                if(candidate == ID[i])
                    nTimes++;
                else
                    nTimes--;
    
            }
    
        }
        return candidate;
    }

    扩展问题2:

      如果数组中的3个数字个数都分别超过了数组长度的1/4,又该如何查出它们?

    问题分析:

      每次绑定三个id,同时加减。


    代码实现:

    #include <stdio.h>
    
    void Find(int* ID, int N);
    
    int main(void)
    {
        int ID[] = {5,6,7,1,2,1,2,1,2,3,3,4,3,2,1,3,2,1,2,1,3};
        Find(ID,21);
        return 0;
    }
    void Find(int* ID, int N)
    {
        int nTimes[3], i;
        int candidate[3];
        nTimes[0]=nTimes[1]=nTimes[2]=0;
        candidate[0]=candidate[1]=candidate[2]=-1;
        for(i = 0; i < N; i++)
        {
            if(ID[i]==candidate[0])//这几个并列的思想很重要,好好想想
            {
                 nTimes[0]++;
            }
            else if(ID[i]==candidate[1])
            {
                 nTimes[1]++;
            }
            else if(ID[i]==candidate[2])
            {
                 nTimes[2]++;
            }
            else if(nTimes[0]==0)
            {
                 nTimes[0]=1;
                 candidate[0]=ID[i];
            }
            else if(nTimes[1]==0)
            {
                 nTimes[1]=1;
                 candidate[1]=ID[i];
            }
            else if(nTimes[2]==0)
            {
                 nTimes[2]=1;
                 candidate[2]=ID[i];
            }
            else//新的id和已选的三个id不同的时候,让已选的三个id同时-1
            {
                 nTimes[0]--;
                 nTimes[1]--;
                 nTimes[2]--;
             }
        }
        printf("id:   %d %d %d
    ",candidate[0],candidate[1],candidate[2]);
        printf("times:%d %d %d
    ",nTimes[0],nTimes[1],nTimes[2]);
        return;
    }
  • 相关阅读:
    查看内置命令和非内置命令帮助的几种方法(man、help、info)
    手写js的insertAfter
    Java 单链表简单实现
    StudentMain控屏后如何关闭
    python3 twisted问题
    python3 you-get
    数据库方言(这是啥玩意儿?)
    vi/vim用法
    sublime text3
    数据库命令大全(也不是很全哈)
  • 原文地址:https://www.cnblogs.com/tractorman/p/4116154.html
Copyright © 2020-2023  润新知