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

被折叠的 条评论
为什么被折叠?



