编程题-丢失的数

题目:

给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。

解法一(排序):

将数组排序后,可根据数组中每个下标处元素是否和下标相等,找到丢失的数字。由于数组的长度是n,因此下标范围是[0, n-1],假设缺失的数组是k,当0≤k<n时,对任意0≤i<k,都有nums[i]=i,由于k缺失,因此nums[k]=k+1,k是第一个满足下标和元素不相等的下标;当k=n时,0到n-1都没有缺失,因此对任意0≤i<n,都有nums[i]=i。

根据上述两种情况,可以得到如下方法得到丢失的数字:

1、从左到右遍历数组 nums,如果存在 0≤i<n 使得 nums[i]=i,则缺失的数字是满足 nums[i]=i 的最小的 i;

2、如果对任意 0≤i<n,都有 nums[i]=i,则缺失的数字是 n。如下为所示代码:

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        //对容器vector数组nums进行排序sort()
        sort(nums.begin(),nums.end());
        int n = nums.size();
        //一次遍历数组,数组下标不等于数组值时返回丢失数字,若遍历完仍没有查找到时,即为数字n(末端)
        for (int i = 0; i < n; i++) {
            if (nums[i] != i) {
                return i;
            }
        }
        return n;
    }
};

特别注意:sort 函数是用于对vector容器中的元素进行排序的一个算法,通常定义在 <algorithm> 头文件中。它可以对一个范围内的元素进行排序,默认按照升序排序,但也可以通过自定义比较函数来实现降序或其他排序方式。例如sort(nums.begin(),nums.end()) 按升序排列。

void sort(RandomIt first, RandomIt last, Compare comp);

firstlast:指定要排序的范围,first 是范围的起始迭代器,last 是范围的末尾迭代器

comp:是一个二元谓词函数,接受两个元素作为参数并返回布尔值。comp 返回 true 时,表示第一个元素应该排在第二个元素之前(升序排序),返回 false 则反之。如果不提供该参数,sort 会默认按照升序排列。

解法二(哈希表):

首先遍历数组 nums,将数组中的每个元素加入哈希集合,然后依次检查从 0 到 n 的每个整数是否在哈希集合中,不在哈希集合中的数字即为丢失的数字。由于哈希集合的每次添加元素和查找元素的时间复杂度都是 O(1),因此总时间复杂度是 O(n)。如下为笔者代码:

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int n = nums.size();
        unordered_map<int,int> hashTable1;
        for(int i=0; i<n; i++){
            hashTable1[nums[i]]=nums[i];
        }
        for(int i=0; i<n+1;i++){
            if(hashTable1.count(i)>0){
                continue;
            }
            else{
                return i;
            }
        }
        return 0;
    }
};

时间复杂度为O(n),其中n是数组nums的长度。遍历数组nums将元素加入哈希表的时间,以及遍历从0到n每个整数是否在哈希表中的时间复杂度均是O(n)。空间复杂度是O(n),其中n是数组nums的长度。哈希表中需要存储n个整数

解法三(位运算):

数组nums中有n个数,在这n个数后面添加从0到n的每个整数,则添加了n+1个整数,共有2n+1个整数,在2n+1个整数中,丢失的数字只在后面n+1个整数中出现一次,其余的数字在前面n个整数中(即数组中)和后面n+1个整数中各出现一次,即其余的数字都出现了两次。

根据出现的次数的奇偶性,可以使用按位异或运算得到丢失的数字。按位异或运算满足交换律和结合律,对任意整数x都满足x⊕x=0 和 x⊕0=x。由于上述2n+1个整数中,丢失的数字出现了一次,其余的数字都出现了两次,因此对上述2n+1个整数进行按位异或运算,结果即为丢失的数字,实现代码如下所示:

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int res = 0;
        int n = nums.size();
        //先将nums数字进行位异或运算
        for (int i = 0; i < n; i++) {
            res ^= nums[i];
        }
        //再将新添加的n+1个整数进行位异或运算
        for (int i = 0; i <= n; i++) {
            res ^= i;
        }
        return res;
    }
};

位运算实现的代码的时间复杂度为O(n),其中n是数组nums的长度,需要对2n+1个数字计算按位异或的结果,空间复杂度为O(1):在运算过程中,没有进入新的数据结构对数据进行存储,位运算不需要存储空间复杂度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值