数组与矩阵---数组中未出现的最小正整数

【题目】

  给定一个无序整型数组arr,找到数组中未出现的最小正整数。
  例如:
  arr = [-1, 2, 3, 4],返回1
  arr = [1, 2, 3, 4],返回5

【基本思路】

  整个过程可以做到时间复杂度O(N),空间复杂度O(1)
  
  生成变量left和right,left表示遍历到目前为止,数组中已经包含的正整数的范围是[1…left],初始时令left = 0表示没有arr目前没有包含任何正整数;right表示遍历到目前为止,在后续情况出现最优的情况下,arr可能包含的正整数的范围是[1, right],初始时令right = N,表示arr可能包含1~N的所有正整数。
  
  利用left从左到右遍历数组:

  1. 如果arr[left] = left + 1。在没有遍历arr[left]之前,arr已经包含的正整数的范围是[1,left],此时出现了arr[left] = left + 1,说明arr包含的正整数的范围可以扩到[1, left+1],即令left + 1.

  2. 如果arr[left] <= left。在没有遍历arr[left]之前,arr中的正整数的范围已经是[1, left],所以需要的是[left+1, right]上的数,而此时arr[left] <= left,说明[left+1, right]上少了一个数,所以arr在后续最优的情况下,可能包含的正整数的范围缩小到[1, right-1],此时把arr最后位置的数arr[r-1]放在位置left上,下一步检查这个数,然后令right - 1.

  3. 如果arr[left] > right,与步骤2同理,把arr最后位置的数arr[r-1]放在位置left上,下一步检查这个数,然后令right - 1.

  4. 如果arr[arr[left]-1] = arr[left]。如果步骤2、3没中,说明arr[left]是在[left+1, right]范围上的,而且这个数应该放置在arr[left] - 1位置上,但是发现此时arr[left] - 1位置上的数已经为arr[left],说明这个数出现了两次,既然在[left+1, right]上出现了重复值,那么[left+1, right]范围上的数又少了一个,所以把arr最后位置的数arr[r-1]放在位置left上,下一步检查这个数,然后令right - 1.

  5. 如果步骤2、3、4都没中,说明发现了[left+1, right]上的数,并且未发生重复。那么arr[left]应该放在位置arr[left] - 1上,所以把left位置上的值和arr[left] - 1位置上的值交换,下一步继续遍历位置left上的数。

下面是使用python3.5实现的代码。

def missNum(arr):
    if arr == None or len(arr) == 0:
        return
    left = 0
    right = len(arr)
    while left < right:
        if arr[left] == left + 1:
            left += 1
        elif arr[left] <= left or arr[left] > right or arr[arr[left]-1] == arr[left]:
            arr[left] = arr[right-1]
            right -= 1
        else:
            tmp = arr[left]
            arr[left] = arr[arr[left]-1]
            arr[tmp-1] = tmp
    return left + 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值