C# 巧妙计算小R输漏掉的一位同学

找遗漏学号算法
本文介绍了一种通过等差数列求和原理找到遗漏学号的方法,并提供了两种实用的编程解决方案,一种使用数组求和,另一种使用异或运算符。

小R的班级一共有n+1个同学。小R做事情比较马虎,他在帮老师输入所有同学学号的时候,不小心漏掉了一位同学。想在这已经输入的n个学号中找出被遗漏的那个学号,需要非常好的眼力。
假设班级同学的学号从1~n+1。聪明的你能编程帮一帮小R同学吗?

输入

测试样例由多组测试数据组成。
每个样例包含两行,第一行输入一个整数n,表示小R已经正确输入的同学的人数;
第二行输入n个整数ai,其中每个 ai各不相同,并且1<=ai<=n+1
10<=n<1000

输出

对于每个样例,输出被小R遗漏的那个同学的学号。

样例输入

3
1  4  2

5
1 3 6 4 2

样例输出
3

5

这个咋解决呢?其实我看到这个题的时候就抓住 “同学的学号从1~n+1 ”关键字,其就是等差数列呀!!!那么这个题我们就从等差数列入手。

对n+1数列公式求和,然后对输入的数组求和,相减就能得到漏掉的同学的学号。

例如:

案例中的数组1,4,2,本来四个人,结果漏掉了3,我对数列1,2,3,4求和(等差数列求和)减去输入的数组求和,不就是漏掉的嘛。

如图:

输入的n记得加一,因为输入n是指正确的n位同学,漏掉一位,所以一共有n+1位,所以截图中我写了3+1,5+1.

这个思路时间复杂度是O(n),主要是arr.Sum()求和耗时(输入的数组求和耗时),其它几乎不耗时。 

虽然此方法比较不错,但是也有缺点,就是在计算数组求和时可能会溢出,可以把int换成long,但是这不是最好的办法,如果n很大很大的话就不适合了。

可以暴力循环,虽然效率低,但是不会溢出,如果数组很长的话也会超时。

最后,等差数列求和,人家欧拉小学都知道(首项+末项)*项数/2。

暴力寻找代码:

         static int FindStudentId2(int[] arr, int n)
        {
            int j,target=-1,m=n,k=m-1;
            n += 1;
            bool status = true;
            for (int i = 1; i <= n; i++)
            {
                for (j = 0; j < m; j++)
                {
                    if (i == arr[j])
                        break;
                    if(j==k)
                        status = false;
                }
                if(!status)
                {
                    target = i;
                    break;
                }
            }
            return target;
        }

技巧代码如下:

        static int FindStudentId(int[] arr,int n)
        {
            n += 1;
            return ((1 + n) * n >> 1) - arr.Sum();
        }

我们还可以利用异或运算符去找,关于异或运算符得法则自己去百度吧,这里就不介绍了;

思路:我们知道x^x=0,0^x=x,所以利用这个特性先连续异或整个数组,然后在连续异或全部数字就能得到遗漏得数字,如下:

        static int FindStudentId3(int[] arr, int n) 
        {
            int flag = 0;
            for (int i = 0; i < n; i++)
            {
                flag ^= arr[i];
            }
            for (int i = 0; i <= n; i++)
            {
                flag ^= i;
            }
            return flag;
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值