簡體   English   中英

Python - 查找第二小的數字

[英]Python - Find second smallest number

我在這個網站上找到這段代碼來找到第二大數字:

def second_largest(numbers):
    m1, m2 = None, None
    for x in numbers:
        if x >= m1:
            m1, m2 = x, m1
        elif x > m2:
            m2 = x
    return m2

來源: 在線性時間內獲取列表中第二大的數

是否可以修改此代碼以找到第二的數字? 例如

print second_smallest([1, 2, 3, 4])
2
a = [6,5,4,4,2,1,10,1,2,48]
s = set(a) # used to convert any of the list/tuple to the distinct element and sorted sequence of elements
# Note: above statement will convert list into sets 
print sorted(s)[1] 

該函數確實可以修改為找到第二小的:

def second_smallest(numbers):
    m1 = m2 = float('inf')
    for x in numbers:
        if x <= m1:
            m1, m2 = x, m1
        elif x < m2:
            m2 = x
    return m2

舊版本依賴於 Python 2 實現細節,即None總是排在其他任何東西之前(因此它測試為“更小”); 余取代了使用float('inf')作為定點,如無窮大總是測試作為比任何其他數量 理想情況下,原始函數應該使用float('-inf')而不是None ,以免與其他 Python 實現可能不共享的實現細節相關聯。

演示:

>>> def second_smallest(numbers):
...     m1 = m2 = float('inf')
...     for x in numbers:
...         if x <= m1:
...             m1, m2 = x, m1
...         elif x < m2:
...             m2 = x
...     return m2
... 
>>> print(second_smallest([1, 2, 3, 4]))
2

在您找到的函數之外,使用heapq.nsmallest()函數從迭代中返回兩個最小值,並從這兩個值中選擇第二個(或最后一個)值幾乎同樣有效。 我已經包含了unique_everseen()配方的一個變體來過濾掉重復的數字:

from heapq import nsmallest
from itertools import filterfalse

def second_smallest(numbers):
    s = set()
    sa = s.add
    un = (sa(n) or n for n in filterfalse(s.__contains__, numbers))
    return nsmallest(2, un)[-1]

和上面的實現一樣,這是一個 O(N) 的解決方案; 保持堆變量的每一步都需要 logK 時間,但 K 在這里是一個常數 (2)!

無論你做什么,都不要使用排序 這需要 O(NlogN) 時間。

或者只是使用heapq

import heapq
def second_smallest(numbers):
    return heapq.nsmallest(2, numbers)[-1]

second_smallest([1, 2, 3, 4])
# Output: 2

根據 Python 內置函數sorted

sorted(my_list)[0]

返回最小的數字, sorted(my_list)[1]對第二小的數字進行相應的處理,依此類推。

我最喜歡的查找第二小的數字的方法是從列表中刪除最小的數字,然后從列表中打印最小值將返回列表中第二小的元素。 任務代碼如下:

mylist=[1,2,3,4]
mylist=[x for x in mylist if x!=min(mylist)]  #deletes the min element from the list
print(min(mylist))
def second_min_index(ls):
    min_value = min(ls)
    max_value = max(ls)

    # The smallest number changes into the largest.
    for value in ls:
        if value == min_value:
            ls[ls.index(value)] = max_value

    return ls.index(min(ls))

是的,除了代碼依賴於一個小怪癖(在 Python 3 中引發異常): None比較小於數字的事實。

另一個有效的值是float("-inf") ,它是一個比任何其他數字都小的數字。

如果您使用它而不是None ,並將-inf更改為+inf並將>更改為< ,則沒有理由它不起作用。

編輯:另一種可能性是簡單地寫-x在所有比較x ,例如做if -x <= m1:等等。

返回列表中第二個唯一數字且不排序的解決方案:

def sec_smallest(numbers):
    smallest = float('+inf')
    small = float('+inf')
    for i in numbers:
        if i < smallest:
            small = smallest
            smallest = i
        elif i < small and i != smallest:
            small = i
    return small

print('Sec_smallest:', sec_smallest([1, 2, -8, -8, -2, 0]))
 mi= min(input_list)
    second_min = float('inf')
    for i in input_list:
        if i != mi:
            if i<second_min:
                second_min=i
    if second_min == float('inf'):
        print('not present')
    else:
        print(second_min)
             

##input_list = [6,6,6,6,6]
#input_list = [3, 1, 4, 4, 5, 5, 5, 0, 2, 2]
#input_list = [7, 2, 0, 9, -1, 8]
# Even if there is same number in the list then Python will not get confused.

我想添加另一種更通用的方法:
這是查找給定數字列表的第 i 個最小值的遞歸方法

def find_i_minimums(numbers,i):
    minimum = float('inf')
    if i==0:
        return []
    less_than_i_minimums = find_i_minimums(numbers,i-1)
    for element in numbers:
        if element not in less_than_i_minimums and element < minimum:
            minimum = element
    return less_than_i_minimums + [minimum]

例如,

>>> find_i_minimums([0,7,4,5,21,2,6,1],3) # finding 3 minimial values for the given list
[0, 1, 2]

(如果您只想要第 i 個最小數字,您將提取列表的最終值)

不過,上述算法的時間復雜度很糟糕,它是 O(N*i^2) (由於遞歸深度是 i ,並且在每次遞歸調用時,我們都會檢查長度為 N 的“數字”列表中的所有值,並且我們檢查我們正在搜索的最小元素是否不在長度為 i-1 的列表中,因此總復雜度可以用幾何總和來描述,該幾何總和將給出上述復雜度)。

這是一個類似但替代的實現,其時間復雜度平均為 O(N*i)。 它使用 python 的內置“set”數據結構:

def find_i_minimums(numbers,i):
    minimum = float('inf')
    if i==0:
        return set()
    less_than_i_minimums = find_i_minimums(numbers,i-1)
    for element in numbers:
        if element not in less_than_i_minimums and element < minimum:
            minimum = element
    return less_than_i_minimums.union(set({minimum}))

如果你的“i”很小,你可以使用上面的實現,然后提取你想要的最小值(或者如果你想要第二個最小值,那么在你的情況下運行 i=2 的代碼,然后從輸出數據結構)。 但是,例如,如果 'i' 大於 log(N) ,我建議對數字列表本身進行排序(例如,在最壞的情況下使用復雜度為 O(N*log(N)) 的歸並排序),然后采用第 i 個元素。 為什么這樣? 因為如上所述,對於較大的“i”值,上述算法的運行時間並不是很好。

您可能會發現此代碼簡單易懂

def secsmall(numbers):
small = max(numbers)
for i in range(len(numbers)):
    if numbers[i]>min(numbers):
        if numbers[i]<small:
            small = numbers[i]
return small

我假設“數字”是一個列表名稱。

在整數數組中找到第一個和第二個最小的數字

arr= [1,2,3,4,5,6,7,-1,0,-2,-10]
def minSecondmin(arr,n):
  i=1
  if arr[i-1] < arr[i]:
    f = arr[i-1]
    s = arr[i]
  else:
    f=arr[i]
    s=arr[i-1]

  for i in range(2,n):
    if arr[i]<f:
      s=f
      f = arr[i]
    elif arr[i]<s:
      s=arr[i]
  return f,s

minSecondmin(arr,len(arr))

在這里,我們希望在掃描數字列表時保持不變,對於每個子列表,它必須是

m1<=m2<={all other elements}

問題(第二小)合理的列表的最小長度是 2,所以我們建立不變量檢查列表的第一個和第二個元素(不需要幻數),接下來我們迭代所有剩余的數字,保持我們的不變性。

def second_smaller(numbers):
    # if len(numbers)<2: return None or otherwise raise an exception

    m1, m2 = numbers[:2]
    if m2<m1: m1, m2 = m2, m1

    for x in numbers[2:]:
        if x <= m1:
            m1, m2 = x, m1
        elif x < m2:
            m2 = x
    return m2

附錄

順便說一句,同樣的推理應該適用於 OP 提到的second_largest函數

l = [41,9000,123,1337]

# second smallest
sorted(l)[1]
123


# second biggest
sorted(l)[-2]
1337

我正在編寫使用遞歸查找列表中第二小的元素的代碼。

def small(l):
 small.counter+=1;
 min=l[0];

 emp=[]

 for i in range(len(l)):
    if l[i]<min:
        min=l[i]

 for i in range(len(l)):
    if min==l[i]:
     emp.append(i)

 if small.counter==2:
    print "The Second smallest element is:"+str(min)
 else:
   for j in range(0,len(emp)):

     l.remove(min)

   small(l)
small.counter = 0

list=[-1-1-1-1-1-1-1-1-1,1,1,1,1,1]
small(list)

您可以使用各種輸入整數對其進行測試。

有一個簡單的方法可以做到。 首先對列表進行排序並從列表中獲取第二項。

def solution(a_list):

    a_list.sort()
    print a_list[1]

solution([1, 2, -8, -2, -10])

您可以在內置函數“已排序”中使用

def second_smallest(numbers):

count = 0
l = []
for i in numbers:
    if(i not in l):
        l.append(i)
        count+=1
    if(count==2):
        break

return max(l)

要在列表中找到第二小的,可以使用以下方法,如果重復兩個或多個元素,該方法將起作用。

def second_smallest(numbers):
     s = sorted(set(numbers))
     return s[1]

這是:

def find_second_smallest(a: list) -> int:
    first, second = float('inf')
    for i in range(len(a)):
        if a[i] < first:
            first, second = a[i], first
        elif a[i] < second and a[i] != first:
            second = a[i]
    return second

輸入:[1, 1, 1, 2]
輸出:2

此代碼也可以正常工作,以查找列表中第二小的數字。 對於此代碼,首先我們必須對列表中的值進行排序。 之后我們必須將變量初始化為第二個索引。

l1 = [12,32,4,34,64,3,43]
for i in range(0,len(l1)):
       for j in range(0,i+1):
          if l1[i]<l1[j]:
              l1[i],l1[j]=l1[j],l1[i]
min_val = l1[1]
for k in l1:
   if min_val>k:
       break
print(min_val)
def SecondSmallest(x):
    lowest=min(x[0],x[1])
    lowest2 = max(x[0],x[1])
    for item in x:
         if item < lowest:
            lowest2 = lowest
            lowest = item
         elif lowest2 > item and item > lowest:
            lowest2 = item
    return lowest2

SecondSmallest([10,1,-1,2,3,4,5])

暫無
暫無

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

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