LeetCode-困难进阶-41-缺失的第一个正数-原地解决(C)

文章首发及后续更新:https://mwhls.top/1615.html
新的更新内容请到mwhls.top查看。
无图/无目录/格式错误/更多相关请到上方的文章首发页面查看。

这题是我解决的第一道困难的LeetCode,值得纪念。
而且还完成了进阶要求!

题目

给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。

进阶:你可以实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案吗?

示例 1:

输入:nums = [1,2,0]
输出:3
示例 2:

输入:nums = [3,4,-1,1]
输出:2
示例 3:

输入:nums = [7,8,9,11,12]
输出:1
 

提示:

0 <= nums.length <= 300
-231 <= nums[i] <= 231 - 1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/first-missing-positive
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路
  • 这题能满足进阶要求,但只是因为这题的nums[]数组大小有限,如果nums[]大小不限,这题无法满足常数项的额外空间。
  • 这题是找最小未出现的正整数,那么如果nums[]的大小为numsSize,则最小未出现的正整数,一定在1~numsSize+1之间。
  • 为了记录所有出现过的数,设置一个numsSize[]大小的hasAppeared[]数组,用来记录nums[]出现的数,且由于最小未出现正整数<=numsSize+1,hasAppeared[]只需要numsSize大小即可。
    • hasAppeared[n]里的值,表示n+1是否出现过,用1表示出现过,非1表示未出现过。
      • C语言中,未初始化的数组可能是随机值,也可能是0,这题在LeetCode的编译器里直接用1表示不会出现问题。
  • 那么在代码里面只需要这么做即可:
    • 设置一个numsSize大小的hasAppeared[]数组。
    • 遍历nums[],如果nums[pos]的值是<=numsSize的正整数,那么就将hasAppeared[ nums[pos]-1 ]的值置为1。
    • 遍历完nums[]后,再遍历hasAppeared[],第一个非1的位置即是所求的未出现的最小正整数,如果全1,则是第numsSize+1为未出现的最小正整数。
  • 例如:
    • 对于nums[] = {1, 0, 2};hasAppeared[]的情况为{1, 1, ?}。第一个非1位hasAppeared[2],因此return 2+1,即pos+1
    • 对于nums[] = {1, 2, 3};hasAppeared[]的情况为{1, 1, 1}。全1,因此return 3+1,即numsSize+1。
      • 注:全1时的遍历结束后,pos == numsSize,因此两种情况均可return pos+1。
  • 进阶:你可以实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案吗?
    • 代码时间复杂度为O(n)+O(n),即O(n)。
    • 使用了n的不定空间。
      • 对于本题来说,numsSize不超过300,因此可以将长度为n的不定空间改成长度为300的空间,就可以满足进阶要求了。
    • 如果要实现原地解决的话,我的想法在现在的基础上改进:
      • 依然是遍历nums[],如果0<nums[pos]<=numsSize,就交换nums[pos]和nums[ nums[pos]-1 ],再将nums[pos]置1。
      • 然后对nums[]执行如上hasAppeared的操作。
    • 是的,我想完想法发现好简单然后顺便实现了!
    • 现在是只需要两个int就能解决了!
    • 改进完发现原来的还缺点东西,新的思路是这样的:
      • 遍历nums[],如果nums[pos] != pos+1,那么交换nums[pos]与nums[ nums[pos]-1 ],并将pos--。
      • 结束后,遍历一遍nums[],如果全符合nums[pos] == pos+1,就返回numsSize,否则返回pos+1。
代码-普通
/*
设置一个hasAppeared的int数组,大小为numsSize。
如果出现了这个数,就将hasAppeared置1,将nums[]遍历,
结束后,将hasAppeared遍历,如果全为1就表明1~numsSize全出现了,返回numsSize+1
否则返回第一个非1的。
*/

int firstMissingPositive(int* nums, int numsSize){
    int *hasAppeared = (int*)malloc(sizeof(int)*numsSize);
    int pos;
    for(pos=0;  pos<numsSize;   pos++){
        if(nums[pos]<=numsSize && nums[pos]>0) hasAppeared[ nums[pos]-1 ] = 1;
    }
    for(pos=0;  pos<numsSize;   pos++){
        if(hasAppeared[pos] != 1) return pos+1;
    }
    return pos+1;
}
代码-进阶
/*
遍历nums[],如果nums[pos] != pos+1,那么交换nums[pos]与nums[ nums[pos]-1 ],并将pos--。
结束后,遍历一遍nums[],如果全符合nums[pos] == pos+1,就返回numsSize,否则返回pos+1。
*/

int firstMissingPositive(int* nums, int numsSize){
    int pos, temp;
    for(pos=0;  pos<numsSize;   pos++){
        if(nums[pos]<=numsSize && nums[pos]>0 && nums[pos]!=pos+1) {
            temp = nums[pos];
            nums[pos] = nums[ temp-1 ];
            nums[ temp-1 ] = temp;
            if(nums[pos] == nums[temp-1]) nums[pos]=-1;
            pos--;
        }
    }
    for(pos=0;  pos<numsSize;   pos++){
        if(nums[pos] != pos+1) return pos+1;
    }
    return pos+1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LeetCode-Editor是一种在线编码工具,它提供了一个用户友好的界面编写和运行代码。在使用LeetCode-Editor时,有时候会出现乱码的问题。 乱码的原因可能是由于编码格式不兼容或者编码错误导致的。在这种情况下,我们可以尝试以下几种解决方法: 1. 检查文件编码格式:首先,我们可以检查所编辑的文件的编码格式。通常来说,常用的编码格式有UTF-8和ASCII等。我们可以将编码格式更改为正确的格式。在LeetCode-Editor中,可以通过界面设置或编辑器设置来更改编码格式。 2. 使用正确的字符集:如果乱码是由于使用了不同的字符集导致的,我们可以尝试更改使用正确的字符集。常见的字符集如Unicode或者UTF-8等。在LeetCode-Editor中,可以在编辑器中选择正确的字符集。 3. 使用合适的编辑器:有时候,乱码问题可能与LeetCode-Editor自身相关。我们可以尝试使用其他编码工具,如Text Editor、Sublime Text或者IDE,看是否能够解决乱码问题。 4. 查找特殊字符:如果乱码问题只出现在某些特殊字符上,我们可以尝试找到并替换这些字符。通过仔细检查代码,我们可以找到导致乱码的特定字符,并进行修正或替换。 总之,解决LeetCode-Editor乱码问题的方法有很多。根据具体情况,我们可以尝试更改文件编码格式、使用正确的字符集、更换编辑器或者查找并替换特殊字符等方法来解决这个问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值