[LC优选算法#10] 二分 | 点名

1. 点名

点名

解题思路:

这道题有很多解法,但是时间复杂度基本都是O(N)

  1. 哈希表:遍历数组统计0~n每个元素出现的次数,再次遍历找出缺失的数字。

  2. 遍历数组:遍历数组直至遇到下标与元素不相等的位置,返回下标。

  3. 位运算:将数组中的元素全部异或^,结果即为缺失的数字。

  4. 求和:求出0 ~ n的和后逐一减去数组中的元素,结果即为缺失的数字。

  5. 二分查找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;
    }
};

// 本期内容就到这里啦,如果对你有帮助,请三连支持!我是青云,我们下期见^_~