[英]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.