• 人人校招笔试题


    人人校招笔试题

                                                 ---9月22日,人人校招笔试题

    1、给定一个有序数组a,长度为len,和一个数X,判断A数组里面是否存在两个数,他们的和为X,bool judge(int *a, int len, int x),存在返回true,不存在返回false

    2、给定有n个数的数组a,其中超过一半的数为一个定值,在不进行排序、不开设额外数组的情况下,以最高效的算法找到这个数:int find(int *a, int n)

     

    题解:(转载请联系博主,个人看法,仅供参考!)

    1、给定一个有序数组a,长度为len,和一个数X,判断A数组里面是否存在两个数,他们的和为X,bool judge(int *a, int len, int x),存在返回true,不存在返回false

    解:  注意仔细研究题目中的条件,比如关键的一句,有序数组a,这是一个有序的数组,这一点十分重要!

    思路1:遍历,时间复杂度为O(N2),很显然,这种方法没什么实际意义,而且题目中说了这个一个有序数组,采用遍历的方法是你想不出其他解法时的最坏选择而已!

    思路2:根据有序数组的特点,要么递增要么递减,这个时候我们不要凭空想象,拿出纸和笔,举一个实例来分析是最好的方法,

     

      算法的思路通过上图可以清晰的表现出来,这里再简单叙述一下:申请一个与原数组a[N]一样长度的内存空间arr[N],用给定的值X减去原数组中的元素,对应的放到申请的内存空间arr[N]中,设置两个指针p和q,分别指向原数组a[N]的最后一个元素和arr[N]的第一个元素,指针移动满足条件:

    指针移动必须满足条件:p和q指针没有越界,越界则跳出

      若指针指向的值相等且i不等于j(添加了条件:i不等于j,避免出现8 = 4 + 4的情况),则返回true;

      若原数组是升序的,那么每次移动指向的值较大的指针;

      若原数组是降序的,那么每次移动指向的值较小的指针;

    移动结束,跳出移动指针的循环,说明不存在,返回false

      在网友( Tyler_cao泡泡腾)的评论中有更加简洁的方法,思路基本一样,借鉴一下!

    code:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    int Judge(int *a, int len, int x)
    {
        int Ascending = 0;//为1表示升序,否则降序
        Ascending = a[1] > a[0] ? 1 : 0;
        int *CopyA = (int *)malloc(sizeof(int) * len);
        memset(CopyA, 0, sizeof(int) * len);
        //构建另一数组
        int icount = 0;
        for(icount = 0; icount < len; icount++)
        {
            CopyA[icount] = x - a[icount];
        }
        //比较两个指针移动的值,这里用索引代替指针
        int i = len - 1, j = 0;
        while(i >= 0 && j < len)
        {
            if(a[i] > CopyA[j])
            {
                switch(Ascending)
                {
                    case 0: j++; break;//降序
                    case 1: i--; break;//升序
                    default:break;
                }
            }
            else if(a[i] == CopyA[j] && i != j)
            {
                return 1;
            }
            else
            {
                switch(Ascending)
                {
                    case 0: i--; break;//降序
                    case 1: j++; break;//升序
                    default:break;
                }
            }
        }
        return 0;
    }
    int main()
    {
        int a[] = {1, 2, 3, 4};
        int len = 4;
        int x = 8;
        switch(Judge(a, len, x))
        {
            case 0: printf("%d isn't exist!", x);break;
            case 1: printf("%d is exist!", x);break;
            default : break;
        }
        return 0;
    }
    View Code

     2、给定有n个数的数组a,其中超过一半的数为一个定值,在不进行排序、不开设额外数组的情况下,以最高效的算法找到这个数:int find(int *a, int n)

    解:审题发现,要求条件蛮多的:不进行排序,不开设额外数组。这道题目其实我没有想到十分有效的方法,题解参考的编程之美2.3寻找发帖“水王”

    算法的思想是:既然在数组中某个定值出现的次数超过一半,那么每次从数组中删除两个不同的数字,直到数组中的元素全部相同为止,最后剩下的数组相同的元素一定就是这个定值,这里使用一个计数器cnt,对数组中某个数VeryNum进行计数,通过计数器的加减来找到该定值。

    算法流程图:

    code:

    #include <stdio.h>
    #include <stdlib.h>
    int find(int *a, int n)
    {
        int VeryNum = 0;
        int cnt = 0;
        int i = 0;
        for(i = 0; i < n; i++)
        {
            if(cnt == 0)
            {
                VeryNum = a[i];
                cnt = 1;
            }
            else
            {
                if(a[i] == VeryNum)
                {
                    cnt++;
                }
                else
                {
                    cnt--;
                }
            }
        }
        return VeryNum;
    }
    int main(void)
    {
        int a[] = {15, 15, 5, 15, 5, 15, 1};
        int n = 7;
        printf("%d
    ", find(a, n));
        return 0;
    }
    View Code
  • 相关阅读:
    MongoDB
    前端框架之vue初步学习
    mysql再回首
    oracle之回顾二
    oracle再回首
    springboot之对之前的补充
    springCloud学习
    springboot-ssm的pom.xml
    MyCat
    11.Java反射机制 哦对了,前面的序号来自随笔关于编程之路的思索第一篇
  • 原文地址:https://www.cnblogs.com/bestDavid/p/ExamnationRenren.html
Copyright © 2020-2023  润新知