I’d like to add another, more general approach:
Here’s a recursive way of finding the i-th minimums of a given list of numbers
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]
For example,
>>> find_i_minimums([0,7,4,5,21,2,6,1],3) # finding 3 minimial values for the given list
[0, 1, 2]
( And if you want only the i-th minimum number you’d extract the final value of the list )
The time-complexity of the above algorithm is bad though, it is O(N*i^2) ( Since the recursion depth is i , and at each recursive call we go over all values in ‘numbers’ list whose length is N and we check if the minimum element we’re searching for isn’t in a list of length i-1, thus the total complexity can be described by a geometric sum that will give the above mentioned complexity ).
Here’s a similar but alternative-implementation whose time-complexity is O(N*i) on average. It uses python’s built-in ‘set’ data-structure:
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}))
If your ‘i’ is small, you can use the implementations above and then extract how many minimums you want ( or if you want the second minimum, then in your case run the code for i=2 and just extract the last element from the output data-structure ).
But if ‘i’ is for example greater than log(N) , I’d recommend sorting the list of numbers itself ( for example, using mergesort whose complexity is O(N*log(N)) at worst case ) and then taking the i-th element. Why so? because as stated, the run-time of the algorithm above is not great for larger values of ‘i’.
Еще одно решение с использованием — array.argpartition() из модуля Numpy (гораздо быстрее работает для больших списков):
import numpy as np
In [45]: a = np.random.randint(0, 100, size=10)
In [46]: a
Out[46]: array([ 8, 51, 63, 31, 21, 9, 28, 19, 70, 57])
In [47]: a.argpartition(2)[:2]
Out[47]: array([0, 5], dtype=int64)
дает такой же результат как и argsort()
In [48]: a.argsort()[:2]
Out[48]: array([0, 5], dtype=int64)
Сравнение производительности для массива из 1.000.000 элемтов:
In [32]: a = np.random.randint(0, 1000, size=10**6)
In [33]: lst = a.tolist()
In [34]: a.shape
Out[34]: (1000000,)
In [35]: len(lst)
Out[35]: 1000000
# Кирилл Малышев
In [51]: %timeit sorted(enumerate(lst), key=lambda x:x[1])[:2]
1.68 s ± 10.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# Alban
In [49]: %timeit smallest(lst, 2)
860 ms ± 5.44 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# jfs
In [37]: %timeit nsmallest(2, range(len(lst)), key=lst.__getitem__)
212 ms ± 4.86 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# avtomato
In [38]: %timeit a.argsort()[:2]
193 ms ± 10.9 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# Sergey Gornostaev
In [36]: %timeit map(lst.index, nsmallest(2, lst))
75.4 ms ± 2.35 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# MaxU
In [39]: %timeit a.argpartition(2)[:2]
10.8 ms ± 37.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
0 / 0 / 0 Регистрация: 23.09.2020 Сообщений: 17 |
|
1 |
|
Вывести второе минимальное число в списке23.03.2021, 14:42. Показов 8680. Ответов 23
Список из 10 элементов заполняется целыми числами. Вывести второе минимальное число в списке.
0 |
Arsegg 3484 / 2092 / 560 Регистрация: 02.09.2015 Сообщений: 5,336 |
||||
23.03.2021, 15:48 |
2 |
|||
2 |
alilxxey 707 / 346 / 120 Регистрация: 09.12.2020 Сообщений: 919 |
||||
23.03.2021, 15:52 |
3 |
|||
0 |
3484 / 2092 / 560 Регистрация: 02.09.2015 Сообщений: 5,336 |
|
23.03.2021, 15:54 |
4 |
a.pop(i) На будущее: удаление элемента из середины (начала) списка выполняется за линейное время
1 |
Автоматизируй это! 7084 / 4385 / 1178 Регистрация: 30.03.2015 Сообщений: 12,826 Записей в блоге: 29 |
|
23.03.2021, 16:13 |
5 |
а почему просто не sorted(a_list)[1] ?
1 |
707 / 346 / 120 Регистрация: 09.12.2020 Сообщений: 919 |
|
23.03.2021, 16:15 |
6 |
Welemir1, это слишком гениально для нас
0 |
Semen-Semenich 4611 / 3148 / 1112 Регистрация: 21.03.2016 Сообщений: 7,842 |
||||
23.03.2021, 17:57 |
7 |
|||
а почему просто не sorted(a_list)[1] не прокатит.
0 |
3484 / 2092 / 560 Регистрация: 02.09.2015 Сообщений: 5,336 |
|
23.03.2021, 18:15 |
8 |
не прокатит. Прокатит, просто медленно.
0 |
99 / 86 / 20 Регистрация: 10.09.2019 Сообщений: 708 |
|
23.03.2021, 18:23 |
9 |
Прокатит, просто медленно. Интересно, только сегодня просматривал данный модуль, вот о чем
0 |
3484 / 2092 / 560 Регистрация: 02.09.2015 Сообщений: 5,336 |
|
23.03.2021, 18:29 |
10 |
AlexMarkov, смотри: под капотом куча. 2 — размер кучи. N — размер списка. 2 <<
1 |
99 / 86 / 20 Регистрация: 10.09.2019 Сообщений: 708 |
|
23.03.2021, 18:30 |
11 |
Делаю вывод, что решение alilxxey, «прокатит по быстрее».
0 |
Status 418 3856 / 2136 / 571 Регистрация: 26.11.2017 Сообщений: 5,004 Записей в блоге: 2 |
|
23.03.2021, 18:32 |
12 |
нужно не второй минимальный элемент находить, а второе минимальное число которого в списке может и не быть.
1 |
Arsegg 3484 / 2092 / 560 Регистрация: 02.09.2015 Сообщений: 5,336 |
||||
23.03.2021, 18:33 |
13 |
|||
Был бы рад увидеть доказательства или услышать,другие точки зрения Тут не может быть других точек зрения, кроме практического «доказательства»:
1 |
99 / 86 / 20 Регистрация: 10.09.2019 Сообщений: 708 |
|
23.03.2021, 18:33 |
14 |
Arsegg, одновременно набирал текст, поэтому данная тематика относиться к выше представленному
0 |
Arsegg 3484 / 2092 / 560 Регистрация: 02.09.2015 Сообщений: 5,336 |
||||
23.03.2021, 18:35 |
15 |
|||
Nuff said:
0 |
Semen-Semenich 4611 / 3148 / 1112 Регистрация: 21.03.2016 Сообщений: 7,842 |
||||||||
23.03.2021, 18:39 |
16 |
|||||||
Прокатит, просто медленно как?
второе минимальное кто сказал что в списке одно первое минимальное? пример (список после сортировки)
первое минимальное это 1 а второе минимальное это 2
1 |
3484 / 2092 / 560 Регистрация: 02.09.2015 Сообщений: 5,336 |
|
23.03.2021, 18:42 |
17 |
как? Посмотрите выше замеры
0 |
AlexMarkov 99 / 86 / 20 Регистрация: 10.09.2019 Сообщений: 708 |
||||
23.03.2021, 18:44 |
18 |
|||
Мои результаты:
0 |
4611 / 3148 / 1112 Регистрация: 21.03.2016 Сообщений: 7,842 |
|
23.03.2021, 18:59 |
19 |
Arsegg, мы немного не поняли друг друга. я относительно
а почему просто не sorted(a_list)[1] ? написал что не прокатит потому что в списке может быть не один первый минимальный а не к вопросу сортировки.
0 |
3484 / 2092 / 560 Регистрация: 02.09.2015 Сообщений: 5,336 |
|
23.03.2021, 19:06 |
20 |
написал что не прокатит потому что в списке может быть не один первый минимальный а не к вопросу сортировки. В списке 10 элементов, как может не прокатить? Если несколько элементов подходят под условие — выводим первый.
0 |
IT_Exp Эксперт 87844 / 49110 / 22898 Регистрация: 17.06.2006 Сообщений: 92,604 |
23.03.2021, 19:06 |
Помогаю со студенческими работами здесь Найти минимальное число ходов, которые нужны шахматному коню для перехода с первого поля на второе
Даны обозначения двух полей шахматной доски…
Число фибоначчи. Как вывести двумерный массив и найти максимальное и минимальное число c_s segment Искать еще темы с ответами Или воспользуйтесь поиском по форуму: 20 |
Функция действительно может быть изменена, чтобы найти вторую наименьшую:
def second_smallest(numbers):
m1, m2 = float('inf'), 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'), 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()
, чтобы вернуть два наименьших значения из iterable, и из этих двух выбрать второе (или последнее) значение:
from heapq import nsmallest
def second_smallest(numbers):
return nsmallest(2, numbers)[-1]
Как и вышеприведенная реализация, это решение O (N); сохраняя вариант кучи, каждый шаг принимает время logK, но K является константой здесь (2)! Что бы вы ни делали, не используйте сортировку; который принимает время O (NlogN).
Найти два наименьших (минимальных) элемента массива
Просмотров 7.7к. Обновлено 15 октября 2021
В одномерном массиве целых чисел определить два наименьших элемента. Они могут быть как равны между собой (оба являться минимальными), так и различаться.
Сначала можно найти минимальный элемент массива. После этого искать второй минимум, исключив их поиска первый с помощью if. Данный способ рассматривается здесь по отношению к двум наибольшим элементам.
Сложнее задачу решить, используя один цикл перебора.
Предположим, что двумя наименьшими элементами массива являются первый и второй элемент. Присвоим их индексы переменным m1 и m2. При этом, если первый элемент меньше второго, то его индекс присвоим m1, иначе m1 получит значение второго элемента, а m2 первого.
Начнем перебирать массив в цикле, начиная с третьего элемента. Если он меньше элемента, чей индекс хранится в m1, то присвоим индекс текущего элемента m1. Иначе (если значение по индексу m1 меньше, чем по индексу i) будем проверять, не меньше ли значение по индексу i, того что по индексу m2.
Есть один не очевидный нюанс. Допустим, в m1 указывало на значение 5, а m2 — на 10. Очередной элемент равен 3. Мы меняем m1, и забываем о числе 5. Однако оно может оказаться как раз вторым минимумом массива.
Поэтому в программе при изменении значения m1 надо предусмотреть проверку, не меньше ли теряемое значение, чем то, что хранится по индексу m2.
Pascal
const
N = 10;
var
a: array[1..N] of integer;
i, min1, min2, buff: byte;
begin
randomize;
for i:=1 to N do begin
a[i] := random(100);
write(a[i]:4);
end;
writeln;if a[1] < a[2] then begin
min1 := 1;
min2 := 2;
end
else begin
min1 := 2;
min2 := 1;
end;for i:=3 to N do
if a[i] < a[min1] then begin
buff := min1;
min1 := i;
if a[buff] < a[min2] then
min2 := buff;
end
else
if a[i] < a[min2] then
min2 := i;writeln('№', min1:2,': ', a[min1]:2);
writeln('№', min2:2,': ', a[min2]:2);
end.
8 66 40 40 0 14 50 74 93 71
№ 5: 0
№ 1: 8
Язык Си
#include < stdio.h>
#define N 10
main() {
int a[N];
int i, min1, min2, buff;
srand(time(NULL));
for (i=0; i< N; i++) {
a[i] = rand() % 100;
printf("%3d", a[i]);
}
printf("n");if (a[0] < a[1]) {
min1 = 0;
min2 = 1;
} else {
min1 = 1;
min2 = 0;
}for (i=2; i< N; i++) {
if (a[i] < a[min1]) {
buff = min1;
min1 = i;
if (a[buff] < a[min2]) min2 = buff;
} else {
if (a[i] < a[min2]) min2 = i;
}
}printf("№%2d:%3dn",min1+1,a[min1]);
printf("№%2d:%3dn",min2+1,a[min2]);
}
97 20 88 29 20 43 87 19 33 26
№ 8: 19
№ 5: 20
Python
найти два минимальных элемента массива python
from random import random
N = 10
a = []
for i in range(N):
a.append(int(random()*100))
print("%3d" % a[i], end='')
print()if a[0] > a[1]:
min1 = 0
min2 = 1
else:
min1 = 1
min2 = 0for i in range(2,N):
if a[i] < a[min1]:
b = min1
min1 = i
if a[b] < a[min2]:
min2 = b
elif a[i] < a[min2]:
min2 = iprint("№%3d:%3d" % (min1+1, a[min1]))
print("№%3d:%3d" % (min2+1, a[min2]))# Вариант 2
from random import randint
array = [randint(1, 20) for i in range(10)]
print(array)min1 = min(array)
array.remove(min1)
min2 = min(array)print(min1)
print(min2)
14 3 40 56 42 43 89 69 64 72
№ 1: 14
№ 2: 3
КуМир
алг два минимальных
нач
цел N = 10
цел таб arr[1:N]
цел i,m1,m2,b
нц для i от 1 до N
arr[i] := irand(10,100)
вывод arr[i]:3
кц
вывод нсесли arr[1] < arr[2] то
m1 := 1
m2 := 2
иначе
m1 := 2
m2 := 1
всенц для i от 3 до N
если arr[i] < arr[m1] то
b := m1
m1 := i
если arr[b] < arr[m2] то
m2 := b
все
иначе
если arr[i] < arr[m2] то
m2 := i
все
все
кц
вывод "№",m1:2,":",arr[m1]:3,нс
вывод "№",m2:2,":",arr[m2]:3,нс
кон
65 32 24 86 65 58 67 55 33 96
№ 3: 24
№ 2: 32
Basic-256
N = 10
dim arr(N)
for i=0 to N-1
arr[i] = int(rand*100)
print arr[i] + " ";
next iif arr[0] < arr[1] then
m1 = 0
m2 = 1
else
m1 = 1
m2 = 0
endiffor i=2 to N-1
if arr[i] < arr[m1] then
b = m1
m1 = i
if arr[b] < arr[m2] then
m2 = b
endif
else
if arr[i] < arr[m2] then
m2 = i
endif
endif
next iprint (m1+1) + ": " + arr[m1]
print (m2+1) + ": " + arr[m2]
81 7 25 71 23 9 56 91 73 64
2: 7
6: 9