Missing Number:从[1, n]中找出缺失的一个数。
这道题应该是微软的面试题,《编程之美》中讲过,该题的另外一个限制就是只能访问二进制位,但是力扣上没有限制,所以就变成了简单题——利用求和公式算出的结果和数组和的差值就是缺失的数。
class Solution {
public:
int missingNumber(vector<int>& nums) {
int sum = accumulate(nums.begin(), nums.end(), 0);
int n = static_cast<int>(nums.size());
return n * (n + 1) / 2 - sum;
}
};
如果只能访问二进制位的话,也可以在O(nlogn)的时间内求出结果,但是还有更好的时间复杂度为O(n)的算法。
当n为奇数时,n的最低有效位为1,设缺失的数位x。因为数据范围从0开始,通过统计已有数组元素的最低有效位,可以算出0和1的个数,同时根据x的最低有效位,满足如下关系:
n是偶数 | n是奇数 | |
|---|---|---|
x是偶数 | 0和1数量相同 | 0比1少一个 |
x是奇数 | 0比1多两个 | 0比1多一个 |
据上表可以确定x的最低有效位。接下来要确定次低有效位,可以把最低有效位不同的数字去掉,只保留最低有效位相同的元素,此时剩下的元素中的次低有效位依然满足0和1相间的关系,递归使用上述解法即可。
class Solution {
private:
int missingNumber(const vector<bitset<32>> &input, int column)
{
if(column >= 32) return 0;
vector<bitset<32>> Zeros, Ones;
for(auto bs : input)
{
if(bs.test(column)) Ones.push_back(bs);
else Zeros.push_back(bs);
}
if(Zeros.size() <= Ones.size()){
int v = missingNumber(Zeros, column + 1);
return (v << 1) | 0;
}
else{
int v = missingNumber(Ones, column + 1);
return (v << 1) | 1;
}
}
public:
int missingNumber(vector<int>& nums) {
vector<bitset<32>> input;
for(int i : nums)
{
input.push_back(bitset<32>(i));
}
return missingNumber(input, 0);
}
};
本文介绍了一种在[1,n]范围内找到缺失数字的高效算法。通过数学公式和二进制位操作,提供了两种解决方案:一种是利用求和公式快速找到结果;另一种是在只能访问二进制位的情况下,通过O(n)时间复杂度的算法确定缺失数字。
3103

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



