Python - 查找第二小的数

20

我在这个网站上找到了这段代码来找到第二大的数字:

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

1
我猜这只是用作练习,对吧?否则,像sorted(numbers)[1]这样的代码可能更可取。 - Tim Pietzcker
@MartijnPieters:好的,我没有想到使用heapq - Tim Pietzcker
@TimPietzcker:仅适用于小于约10k个元素的列表;从算法上讲,这里的方法是O(N),而heapq和sorted分别需要O(NlogK)和O(NlogN),但C的速度在这里胜出算法。 - Martijn Pieters
@gnibbler:然而,这个轮子现在已经供人们使用了。 - Martijn Pieters
@schneck:这还不是回答“我该如何修改此函数以返回第二小的元素”的问题。 - Martijn Pieters
显示剩余4条评论
20个回答

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.

如果您要使用 min() 函数找到最小值,为什么不在过滤后的列表中再次使用 min() 找到最小值呢?second_min = min(v for v in input_list if v != mi) - Martijn Pieters

-1

我正在编写代码,使用递归来查找列表中第二小的元素。

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)

你可以用不同的整数输入来测试它。

-1

你可以使用内置函数 'sorted'

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)

你的代码创建了一个包含两个元素的列表,这两个元素是从numbers中取出的前两个元素,并返回新创建列表中两个元素中的最大值。因此它不能像预期那样正常工作,例如尝试输入:numbers = [0,7,4,5,6,2,1]。你的代码将输出'7',这是错误的(正确的输出应该是'1')。 - jacob12

-1

有一个简单的方法可以做到。首先对列表进行排序,然后获取列表中的第二个项目。

def solution(a_list):

    a_list.sort()
    print a_list[1]

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

1
如果存在可重复的项目,如[1, 1, 2, -8],则代码是错误的。 - Reishin
这取决于上下文。如果您有一个距离原点的物体距离数组,您可能想知道第二近的物体是否与最近的物体距离相同。 - AaronF

-1

这段代码也很好用,用于在列表中查找第二小的数字。 为了使用这段代码,我们首先需要对列表中的值进行排序。然后,我们需要将变量初始化为第二个索引。

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)

-1

在这里,我们希望在扫描数字列表时保持不变量,对于每个子列表,它必须为

m1<=m2<={所有其他元素}

问题(第二小的)合理的最小列表长度为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函数也应该应用同样的推理。


-1
l = [41,9000,123,1337]

# second smallest
sorted(l)[1]
123


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

无法处理 l = [41,41,9000,123,1337],您需要先将其转换为 set,请参见 @Nita 的答案。 - Basj

-1
要在列表中找到第二小的元素,可以使用以下方法,如果有两个或更多元素重复,则该方法将起作用。
def second_smallest(numbers):
     s = sorted(set(numbers))
     return s[1]

-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


1
这与被接受的答案有何不同?请给那个答案点赞,而不是发布完全相同的解决方案。 - razdi

-2
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])

这与我的答案实现有何不同?使用前两个值相比使用float('inf')有什么优势? - Martijn Pieters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接