找到所有数组中消失的数

找到所有数组中消失的数,OJ练习

  • 一、描述
  • 二、方法一
  • 三、方法二

一、描述

给你一个含n个整数的数组nums,其中nums[i]在区间[1,n]内。请你找出所有在[1,n]范围内但没有出现在nums中的数字,并以数组的形式返回结果,本题OJ链接
示例 1:
输入:nums = [4,3,2,7,8,2,3,1]
输出:[5,6]
示例 2:
输入:nums = [1,1]
输出:[2]
提示:
n == nums.length
1 <= n <= 105
1 <= nums[i] <= n
进阶:间复杂度为 O(n) ,空间复杂度为O(1)

二、方法一

采用标记的方式,用空间换时间,开辟一个标记数组,初始化为0,用nums[i]作为标记数组的下标,将对应元素赋值为1,处理完数组nums之后,再遍历一遍标记数组,元素为0的下标就是消失的数字
注意:返回数组不算额外开辟的空间
分析:时间复杂度O(n),空间复杂度O(n)
代码实现:

int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize)
{
    int* flagArr = (int*)calloc(numsSize + 1, sizeof(int)); //开辟标记数组并初始化为0
    int* returnArr = (int*)malloc(sizeof(int) * numsSize); //开辟返回数组
    int i = 0;
    for(i = 0; i < numsSize; i++) //用nums[i]作为标记数组的下标,将对应元素赋值为1
    {
        flagArr[nums[i]] = 1;
    }
    *returnSize = 0;
    for(i = 1; i < numsSize + 1; i++) //检查标记数组并给返回数组赋值
    {
        if(flagArr[i] == 0)
        {
            returnArr[(*returnSize)++] = i;
        }
    }
    return returnArr;
}

三、方法二

采用标记的方式,此方法标记和上一种标记方法不同,不用开辟额外数组,在原数组中标记,数组中的每个元素在[1~n],用每个元素nums[i]的绝对值减1作为数组nums的下标,将对应位置的元素改为负数,表示数字nums[i]出现过,直到处理完所有元素,再遍历一遍数组,为正数的元素下标加1就是消失的数字,注意:同一位置的元素不能重复改为负数,也就是说这个元素是负数的话,就不用再改为负数了,因为负负为正,两次改负数之后,就不能代表它出现过
分析:时间复杂度O(n),空间复杂度O(1)
代码实现:

int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize)
{
    int* returnArr = (int*)malloc(sizeof(int) * numsSize);
    int i = 0;
    for(i = 0; i < numsSize; i++) //遍历
    {
        if(nums[abs(nums[i]) - 1] > 0) //元素为正,才需要改为负数
        {
            nums[abs(nums[i]) - 1] = -nums[abs(nums[i]) - 1];
        }
    }
    *returnSize = 0;
    for(i = 0; i < numsSize; i++) //查找消失的数字,并放到返回数组中
    {
        if(nums[i] > 0)
        {
            returnArr[(*returnSize)++] = i + 1;
        }
    }
    return returnArr;
}

你可能感兴趣的:(OJ,leetcode,算法)