簡體   English   中英

Python 給定一個N個整數的數組A,在O(n)時間復雜度內返回A中沒有出現的最小正數integer(大於0)

[英]Python given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A in O(n) time complexity

例如:

輸入:A = [ 6 4 3 -5 0 2 -7 1 ]

output:5

由於 5 是數組中未出現的最小正數 integer。


我已經為該問題編寫了兩個解決方案。 第一個很好,但我不想使用任何外部庫 + 它的 O(n)*log(n) 復雜性。 當輸入是混沌序列 length=10005(帶負號)時,第二個解決方案“我需要你的幫助來優化它”會出錯。

解決方案 1:

from itertools import count, filterfalse 


def minpositive(a):
    return(next(filterfalse(set(a).__contains__, count(1))))

解決方案 2:

def minpositive(a):
    count = 0
    b = list(set([i for i in a if i>0]))
    if min(b, default = 0)  > 1 or  min(b, default = 0)  ==  0 :
        min_val = 1
    else:
        min_val = min([b[i-1]+1 for i, x in enumerate(b) if x - b[i - 1] >1], default=b[-1]+1)
        
    return min_val

注意:這是 codility 的演示測試,解決方案 1 獲得 100%,解決方案 2 獲得 77%。
“solution2”中的錯誤是由於:
性能測試 -> 中等混沌序列長度=10005(帶負號)得到 3 個預期的 10000
性能測試 -> large chaotic + many -1, 1, 2, 3 (with minus) got 5 expected 10000

在 Python 中測試集合中是否存在數字很快,因此您可以嘗試以下操作:

def minpositive(a):
    A = set(a)
    ans = 1
    while ans in A:
       ans += 1
    return ans

快速用於大型陣列。

def minpositive(arr):
    if 1 not in arr: # protection from error if ( max(arr) < 0 )
        return 1
    else:
        maxArr = max(arr) # find max element in 'arr'
        c1 = set(range(2, maxArr+2)) # create array from 2 to max
        c2 = c1 - set(arr) # find all positive elements outside the array
        return min(c2)

我已經寫了兩個解決方案來解決這個問題。 第一個很好,但我不想使用任何外部庫 + 它的 O(n)*log(n) 復雜度。 當輸入是混亂序列長度=10005(帶減號)時,第二個解決方案“我需要你的幫助來優化它”會出錯。

解決方案1:

from itertools import count, filterfalse 


def minpositive(a):
    return(next(filterfalse(set(a).__contains__, count(1))))

解決方案2:

def minpositive(a):
    count = 0
    b = list(set([i for i in a if i>0]))
    if min(b, default = 0)  > 1 or  min(b, default = 0)  ==  0 :
        min_val = 1
    else:
        min_val = min([b[i-1]+1 for i, x in enumerate(b) if x - b[i - 1] >1], default=b[-1]+1)

    return min_val

注意:這是一個 codility 的演示測試,解決方案 1 為 100%,解決方案 2 為 77%。
“solution2”中的錯誤是由於:
性能測試 -> 中等混亂序列長度 = 10005(帶減號)得到 3 預期 10000
性能測試 -> 大混亂 + 許多 -1, 1, 2, 3(帶減號)得到 5 預期 10000

def minpositive(A):
    """Given an list A of N integers, 
    returns the smallest positive integer (greater than 0) 
    that does not occur in A in O(n) time complexity

        Args:
            A: list of integers
        Returns:
            integer: smallest positive integer

        e.g:
            A = [1,2,3]
            smallest_positive_int = 4
    """
    len_nrs_list = len(A)
    N = set(range(1, len_nrs_list+2))
    
    return min(N-set(A)) #gets the min value using the N integers
    

該解決方案以 100% 的分數通過了性能測試

def solution(A):
    n = sorted(i for i in set(A) if i > 0)  # Remove duplicates and negative numbers
    if not n:
        return 1
    ln = len(n)

    for i in range(1, ln + 1):
        if i != n[i - 1]:
            return i

    return ln + 1

我有一個簡單的解決方案。 無需排序。

def solution(A):
    s = set(A)
    m = max(A) + 2
    for N in range(1, m):
        if N not in s:
            return N
    return 1

注意:這是 100% 總分(正確性和表現)

不使用set我想出了這個解決方案:

 def smallest_missing_positive_integer(A): A.sort() N = len(A) i = 0 previous = 0 while i < N: current = A[i] if current > 0: if current > previous + 1: # breaks consecutiveness return previous + 1 else: previous = current i += 1 return max(previous+1, current+1) 

def solution(A):
    B = set(sorted(A))
    m = 1
    for x in B:
        if x == m:
            m+=1
    return m

從 Niroj Shrestha 和 najeeb-jebreel 繼續,添加了一個初始部分以避免在完整集的情況下進行迭代。 如果陣列非常大,則尤其重要。

def smallest_positive_int(A):
  sorted_A = sorted(A)
  last_in_sorted_A = sorted_A[-1]
  #check if straight continuous list
  if len(sorted_A) == last_in_sorted_A:
    return last_in_sorted_A + 1
  else:
    #incomplete list, iterate to find the smallest missing number
    sol=1
    for x in sorted_A:
        if x == sol:
          sol += 1
        else:
          break
    return sol

A = [1,2,7,4,5,6]
print(smallest_positive_int(A))

這個問題真的不需要另一個答案,但是有一個尚未提出的解決方案,我相信它比迄今為止提出的要快。

正如其他人指出的那樣,我們知道答案在[1, len(A)+1]范圍內,包括在內。 我們可以把它變成一個集合,並取集合中與 A 差的最小元素。這是一個很好的 O(N) 解決方案,因為集合操作是 O(1)。

但是,我們不需要使用 Python 集來存儲[1, len(A)+1] ,因為我們從密集集開始。 我們可以使用數組代替,它將通過列表索引替換集合散列,並為我們提供另一個具有較低常數的 O(N) 解決方案。

def minpositive(a):
    # the "set" of possible answer - values_found[i-1] will tell us whether i is in a
    values_found = [False] * (len(a)+1)
    # note any values in a in the range [1, len(a)+1] as found
    for i in a:
        if i > 0 and i <= len(a)+1:
            values_found[i-1] = True
    # extract the smallest value not found
    for i, found in enumerate(values_found):
        if not found:
            return i+1

我們知道最終的 for 循環總是找到一個未標記的值,因為它比a多一個元素,所以至少它的一個單元格沒有設置為True

def 解決方案(A): len_nrs_list = len(A) N = set(range(1, len_nrs_list+2))

return min(N-set(A))
def check_min(a):
    x= max(a)
    if x-1 in a:
        return x+1
    elif x <= 0:
        return 1
    else:
        return x-1

如果我錯了,請糾正我,但這對我有用。

def solution(A):
clone = 1
A.sort()
for itr in range(max(A) + 2):
    if itr not in A and itr >= 1:
        clone = itr
        break
return clone

print(solution([2,1,4,7]))

#returns 3

我有一個簡單的解決方案。 無需排序。

def solution(A):
    s = set(A)
    for N in range(1, 100002):
        if N not in s:
            return N

注意:這是 100% 總分(正確性和表現)

def solution(A):
    n = 1
    for i in A:
        if n in A:
            n = n+1 
        else:
            return n
    return n
def not_in_A(a):
    a=sorted(a)
    if max(a)<1:
        return(1)
    for i in range(0,len(a)-1):
        if a[i+1]-a[i]>1:
            out=a[i]+1
            if out==0 or out<1:
                continue
            return(out)
            
    return(max(a)+1)

標記然后找到第一個沒找到的

nums = [ 6, 4, 3, -5, 0, 2, -7, 1 ]
def check_min(nums):
    marks = [-1] * len(nums)
    for idx, num in enumerate(nums):
        if num >= 0:
            marks[num] = idx
    for idx, mark in enumerate(marks):
        if mark == -1:
            return idx
    return idx + 1

我剛剛修改了@najeeb-jebreel 的答案,現在該函數給出了一個最佳解決方案。

def solution(A):
    sorted_set = set(sorted(A))
    sol = 1
    for x in sorted_set:
        if x == sol:
            sol += 1
        else:
            break
    return sol

我在比較之前減少了集合的長度

a=[1,222,3,4,24,5,6,7,8,9,10,15,2,3,3,11,-1]
#a=[1,2,3,6,3]
def sol(a_array):
    a_set=set()
    b_set=set()
    cnt=1
    for i in a_array:

        #In order to get the greater performance
        #Checking if element is greater than length+1 
        #then it can't be output( our result in solution)
        
        if i<=len(a) and i >=1:
            
            a_set.add(i) # Adding array element in set 
            b_set.add(cnt) # Adding iterator in set
            cnt=cnt+1
    b_set=b_set.difference(a_set)
    if((len(b_set)) > 1): 
        return(min(b_set))
    else:
        return max(a_set)+1

sol(a)  
def solution(A):
    nw_A = sorted(set(A))
    if all(i < 0 for i in nw_A):
        return 1
    else:
        ans = 1
        while ans in nw_A:
            ans += 1
            if ans not in nw_A:
                return ans

如果有可能導入 numpy 包,以獲得更好的性能。

def solution(A):
    import numpy as np
    nw_A = np.unique(np.array(A))
    if np.all((nw_A < 0)):
        return 1
    else:
        ans = 1
        while ans in nw_A:
            ans += 1
            if ans not in nw_A:
                return ans
def solution(A):
# write your code in Python 3.6
min_num = float("inf")
set_A = set(A)
# finding the smallest number
for num in set_A:
    if num < min_num:
        min_num = num
# print(min_num)

#if negative make positive 
if min_num < 0 or min_num == 0:
    min_num = 1
# print(min_num)

# if in set add 1 until not 
while min_num in set_A:  
    min_num += 1
return min_num

不知道為什么這不是 100% 的正確性。 這是100%的性能

def solution(A):
    arr = set(A)
    N = set(range(1, 100001))
    while N in arr:
       N += 1
    return min(N - arr)

solution([1, 2, 6, 4])
#returns 3

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM