LeetCode Day3统计数组中的元素

448 找到所有数组中消失的数字

题目理解

数组元素在1~n范围内,找到所有缺少的数字。要求不使用
额外空间且时间复杂度为O(n)。

思路

最简单的方法是建立map,将1~n每个数字出现的次数存在map中。考虑不使用额外空间,则需要给已经出现的数字一个标记。类似上文,遍历数组,令a[i]位置的元素取负,当遇到重复元素时,a[i]位置的元素仍为负数,不执行操作,因此最终缺少的元素,以此为下标的数组元素必为正数。

代码

class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        vector<int> res;
        int n=nums.size();
        for(auto i:nums){
            if(nums[abs(i)-1]>0)
                nums[abs(i)-1]*=-1; //一定是i的绝对值,因为原数组中的元素可能已经取反。
        }
        for(int j=0;j<n;j++)
            if(nums[j]>0)
                res.push_back(j+1);
        return res;
    }
};

442 数组中重复的元素

题目理解

数组元素范围1~n,数组中有两种数,一种是只出现一次的数,一种是出现两次的数。找出所有出现两次的元素。

思路

与上题类似,只要在遍历数组时,遇到数组元素已经为负,说明此下标+1代表的数字已经出现过,即为所求。

代码

class Solution {
public:
    vector<int> findDuplicates(vector<int>& nums) {
        vector<int> res;
        int n=nums.size();
        for(auto i:nums){
            if(nums[abs(i)-1]<0)
                res.push_back(abs(i));
            else nums[abs(i)-1]*=-1;
        }
        return res;
    }
};

41 缺失的第一个正数

题目理解

整数数组未排序,其中可能有正数、负数、0,因此上面取负的方法失去作用。进阶是实现时间复杂度为O(n),空间复杂度为常数级别。寻找缺失的第一个正数。

思路

寻找的是缺失的第一个正数,因此负数和0不需要考虑。怎样消除负数和0的影响是需要解决的一个问题。起初我的想法是将所有的负数和0转化为1,前提是要判断1是否缺失。这样再采用取负的方法,遇到的第一个大于0的数的下标+1即为所求。题解中给的思路是将所有小于等于0的元素变为n+1,即可使用取负,思路类似。
第二种思路是将所有的正数与数组下标对应起来,因此需要循环交换数组元素。第一个与元素下标+1不同的元素即为所求。

代码

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int n=nums.size();
        int flag=0;
        for(auto& i:nums)
            if(i==1)
                flag=1;
        if(!flag) return 1;
        for(auto& i:nums)
            if(i<=0)
                i=1;
        for(auto& i:nums)
        {
            if(i<=n&&nums[abs(i)-1]>0) //切记要加i<=n的判断,否则数组会越界
                nums[abs(i)-1]*=-1;
        }
        for(int i=0;i<n;i++)
            if(nums[i]>0)
                return i+1;
        return n+1;
    }
};

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int n=nums.size();
        for(int i=0;i<n;i++)
        {
            while(nums[i]>=1&&nums[i]<=n&&nums[nums[i]-1]!=nums[i])//条件避免死循环
                swap(nums[i],nums[nums[i]-1]);
        }
        for(int i=0;i<n;i++)
            if(nums[i]!=i+1)
                return i+1;
        return n+1;
    }
};
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值