1. 点名
解题思路:
这道题有很多解法,但是时间复杂度基本都是O(N):
-
哈希表:遍历数组统计0~n每个元素出现的次数,再次遍历找出缺失的数字。
-
遍历数组:遍历数组直至遇到下标与元素不相等的位置,返回下标。
-
位运算:将数组中的元素全部
异或^,结果即为缺失的数字。 -
求和:求出
0 ~ n的和后逐一减去数组中的元素,结果即为缺失的数字。 -
二分查找
O(logN):因为数组是升序排列的,这里是否可以尝试用二分算法解决呢?
答案是肯定的。观察发现数组中的元素和下标 存在一定的联系:当区间内的元素没有缺失 时,元素与下标是一一对应 的;但是在缺失 元素之后的区间,下标小于 对应的元素。这样,数组就有了二段性。

显而易见,二分算法的时间复杂度是最优的。
cpp
//二分查找
class Solution {
public:
int takeAttendance(vector<int>& records)
{
int left = 0;
int right = records.size() - 1;
while(left < right)
{
int mid = left + (right - left) / 2;
if(records[mid] == mid)
{
left = mid + 1;
}
else
{
right = mid;
}
}
if(left == records[left]) return left + 1;
return left;
}
};
cpp
哈希表
class Solution {
public:
int takeAttendance(vector<int>& records)
{
vector<int> hash(records.size() + 1, 0);
for(auto x : records)
{
hash[x]++;
}
for(int i=0; i<hash.size(); i++)
{
if(hash[i] == 0)
{
return i;
}
}
return 0;
}
};
cpp
// 直接遍历找结果
class Solution {
public:
int takeAttendance(vector<int>& records)
{
int i;
for(i=0; i<records.size(); i++)
{
if(records[i] != i)
{
return i;
}
}
return i;
}
};
cpp
//异或:相同为0,不同为1
class Solution {
public:
int takeAttendance(vector<int>& records)
{
int ret = 0;
int num = 0;
for(int i=0; i<records.size(); i++)
{
ret ^= records[i];
ret ^= num++;
}
return ret ^= num;
}
};
cpp
//求和相减
class Solution {
public:
int takeAttendance(vector<int>& records)
{
int n = records.size();
int ret = n * (n + 1) / 2; //注意计算公式!
for(auto x : records)
{
ret -= x;
}
if(ret == 0 && records[0] != 0) return 0;
return ret;
}
};
// 本期内容就到这里啦,如果对你有帮助,请三连支持!我是青云,我们下期见^_~