找出不在给定数组中的最小正整数


在leetcode上看到这道题,许多同道给出了惊艳和炫酷的解答方法。

题目:给定一个数组nums,数组中元素均为整数,返回不在nums中的最小正整数

     :type: nums -> list[int]   

   :rtype: i -> integer

   :example: nums = [2,4,7,1,-3,0,5],返回3; nums = [3,2,4,5,6] 返回 1

 

线性时间复杂度的常规实现不难:返回值一定在闭区间[1,k+1]中,创建一个长度为k+1的数组,并全部初始化为0,然后读取原数组,将[1,k]区间内的值写入新数组。最后再返回新数组中第一个0元素的位置 加 1.

算法一(空间复杂度O(N)):

 1 def findmissing(nums):
 2     r = [0] * (len(nums) + 1)
 3     for num in nums:
 4        if 0 < num <= len(nums):
 5             r[num - 1] = 1
 6 
 7     for i in range(len(r)):
 8         if r[i] == 0:
 9             return i + 1
10     

不难看出,空间复杂度为r数组的长度,即O(n).如果在时间复杂度不变的情况下降低空间复杂度,我们需要在原数组中记录信息。

(1)清除无效数据,将小于等于0 和 大于数组长度的值清除;

(2)记录 [1,len(nums)]区间内的值,将目标位置与所在位置的值交换。

算法二(空间复杂度O(1)):

def findmissing(nums):
    i = 0
    while i < len(nums):
        if 0 < nums[i] <= len(nums) and nums[nums[i]-1] != nums[i]:
            nums[nums[i]-1],nums[i] = nums[i], nums[nums[i]-1]
        else:
            i += 1
    
    for i in range(len(nums)):
        if nums[i] != i + 1:
            return i + 1
    return len(nums) + 1

除了采用交换位置的方法记录[1,len(nums)]的值,还可以利用索引来做hash表。

算法三(空间复杂度O(1)):

 1 def findmissing(nums):
 2     # 将无效数据置为0
 3     for i in range(len(nums)):
 4         if nums[i] <=0 or nums[i] > len(nums):
 5             nums[i] = 0
 6 
 7     nums.append(0)
 8     n = len(nums)
 9 
10     for i in range(len(nums)):
11         nums[nums[i] % n] += n
12 
13     for i in range(1,len(nums)):
14         if nums[i] / n == 0:
15             return i
16     return n


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM