Missing Number
Total Accepted: 13285 Total Submissions: 39921 Difficulty: MediumGiven an array containing n distinct numbers taken from 0, 1, 2, …, n, find the one that is missing from the array.
For example,
Given nums = [0, 1, 3] return 2.Note:
Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity?Credits:
Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.
这道题我的想法是将数据分类,即取10的模,因为只缺一个数,所以通过统计每类有多少个数就能进一步找出缺少的数。如图:
我们取模实际上就是将所有数据按个位数分类,我们开一个长为10的数组,分别记录每一类数的个数,缺的那个数对应的那类必然数字个数会比其他类少1,例如:我们例子中,缺的是16,那么个位数为6的那组就会比其他组都少,如图所示。当然这还有个问题就是如果输入的数据不能把每行填满,那么最后的缺的数据对应的那类的数字个数也会比其他的少1,例如图中的个位数为8和个位数为9的情况,但对于这种情况只用取第一个比其他类别少的类别即可,这对于所有情况均适用。
这样我们就能找出缺的数的个位是6了,那么接下来就只考虑个位数是6的数,然后忽略掉个位只看10位,如图:
个位数为6的只有两个数,所以只考虑这两个数,取它们的十位,然后同样取10的模,然后统计每类的数字的个数,找出第一个比其他类的数字个数少的,发现第一个取0的是十位为1对应的那类,所以我们就可以确定缺的那个数的十位是1,当对应的那类的个数为0时,就说明找到了那个数,因为只要大于0,就说明有与缺少那个数具有相同尾数(即到目前为止检测的所有位数)的存在,例如例子中的6和26,但因为每个数都是唯一的,所以无论前面有多少位一样的,总会到某一位时,没有其他数再与它一样,这时候它对应的那类就是0. 所以就可以找出我们缺的那个数是16。这个算法要这样迭代的次数最多等于输入数据中最大数的位数,考虑到输入是整形,范围是−2,147,483,648 to 2,147,483,647最多10位数,所以迭代10次,仍然是线性时间复杂度。
另外一种方法,比这种方法更简单,因为题目会给出将要输入的数据的个数,假设为n,因为知道差一个数,并且数据是连续的,所以完整的数据应该有n+1个数,但是数据是从0开始的,所以最后一个数应该是n,所以完整的数据情况下,所有数的和为: (n+0)(n+1)2=n(n+1)2 , 因为我们知道差了一个数,所以现在的n个数加起来的和与 n(n+1)2 的差距,就是缺的那个数。所以只需用 n(n+1)2 减去现在的n个即可。
下面是完整代码:
#include <iostream>
using namespace std;
//method 1
int missingNumber(int* nums, int numsSize)
{
int missNumber = 0;
int number[10];
int numberIndex = 0;
int tail = 0;
int Min;
int countTable[10];
while(1)
{
memset(countTable, 0, 10 * sizeof(int));
for(int i = 0; i < numsSize; i++)
{
if(nums[i] != -1)
{
int mod = nums[i] % 10;
countTable[mod]++;
}
}
Min = countTable[0];
tail = 0;
for(int i = 1; i < 10; i++)
{
if(countTable[i] < Min)
{
Min = countTable[i];
tail = i;
}
}
/*for(int i = 0; i < 10; i++)
{
cout<<countTable[i]<<"*";
}*/
number[numberIndex++] = tail;
if(Min == 0)
break;
for(int i = 0; i < numsSize; i++)
{
if(nums[i] != -1)
{
if(nums[i] % 10 == tail)
nums[i] /= 10;
else
nums[i] = -1;
}
}
}
for(int i = numberIndex -1; i >= 0; i--)
{
missNumber = missNumber * 10 + number[i];
}
return missNumber;
}
//method 2
int missingNumber2(int* nums, int numsSize)
{
int sum = ((numsSize) + 1) * numsSize / 2;
for(int i = 0; i < numsSize; i++)
{
sum -= nums[i];
}
return sum;
}
int main()
{
int numsSize, *nums;
cout<<"Input the amount of numbers:"<<endl;
cin>>numsSize;
nums = (int*)malloc(sizeof(int) * numsSize);
for(int i = 0; i < numsSize; i++)
cin>>nums[i];
cout<<missingNumber(nums, numsSize);
return 0;
}