Как найти второй минимальный элемент массива питон

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

Python
1
print(__import__("heapq").nsmallest(2, map(int, input().split()))[-1])



2



alilxxey

707 / 346 / 120

Регистрация: 09.12.2020

Сообщений: 919

23.03.2021, 15:52

3

Python
1
2
3
4
5
6
7
a = [1, 2, 3, 4, 5, 6]
k = min(a)
for i in range(len(a)):
    if a[i] == k:
        a.pop(i)
        break
print(min(a))



0



3484 / 2092 / 560

Регистрация: 02.09.2015

Сообщений: 5,336

23.03.2021, 15:54

4

Цитата
Сообщение от alilxxey
Посмотреть сообщение

a.pop(i)

На будущее: удаление элемента из середины (начала) списка выполняется за линейное время O(N).



1



Автоматизируй это!

Эксперт Python

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

Цитата
Сообщение от Welemir1
Посмотреть сообщение

а почему просто не sorted(a_list)[1]

не прокатит.

Python
1
a = [1, 1, 1, 2, 3, 4, 5, 6]



0



3484 / 2092 / 560

Регистрация: 02.09.2015

Сообщений: 5,336

23.03.2021, 18:15

8

Цитата
Сообщение от Semen-Semenich
Посмотреть сообщение

не прокатит.

Прокатит, просто медленно.



0



99 / 86 / 20

Регистрация: 10.09.2019

Сообщений: 708

23.03.2021, 18:23

9

Цитата
Сообщение от Arsegg
Посмотреть сообщение

Прокатит, просто медленно.

Интересно, только сегодня просматривал данный модуль, вот о чем
я был проинформирован при прочтении:

Функции nlargest() и nsmallest() лучше всего подходят, если вы пытаетесь найти
относительно небольшое количество элементов. Если же вы просто хотите найти
один наибольший или наименьший элемент (N = 1), функции min() и max() бу-
дут быстрее. Похожим образом, если N сопоставимо с размером самой коллек-
ции, обычно будет быстрее отсортировать их и взять срез (то есть выполнить
sorted(items)[:N] или sorted(items)[-N:]). Стоит отметить, что реализация nlargest()
и nsmallest() в модуле heapq работает гибко и выполняет некоторые из этих опти-
мизаций самостоятельно (например, использует сортировку, если размер N бли-
зок к размеру входных данных).



0



3484 / 2092 / 560

Регистрация: 02.09.2015

Сообщений: 5,336

23.03.2021, 18:29

10

AlexMarkov, смотри: под капотом куча. 2 — размер кучи. N — размер списка. 2 << N (сильно меньше) => быстрее пройтись по списку и добавлять (заменять) элементы в куче за O(log(2)) => Общая асимтотика: O(N), т. к. log(2) — константа, в большом O она не фигурирует.
P. S. Хотя тут на самом деле двояко: на 10 элементах, возможно, быстрее будет отсортировать квадратичной сортировкой, например, выбором => выйдет быстрее аналогичных (за O(N * log(N))). Нужно смотреть более детально.



1



99 / 86 / 20

Регистрация: 10.09.2019

Сообщений: 708

23.03.2021, 18:30

11

Делаю вывод, что решение alilxxey, «прокатит по быстрее».
Был бы рад увидеть доказательства или услышать, другие точки зрения



0



Status 418

Эксперт Python

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

Цитата
Сообщение от AlexMarkov
Посмотреть сообщение

Был бы рад увидеть доказательства или услышать,другие точки зрения

Тут не может быть других точек зрения, кроме практического «доказательства»:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
In [1]: from random import randrange
 
In [2]: a = [randrange(-1_000, 1_000) for _ in range(10)]
 
In [3]: from heapq import nsmallest
 
In [4]: %timeit nsmallest(2, a)[-1]
4.69 µs ± 79.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
 
In [5]: %timeit sorted(a)[1]
618 ns ± 3.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
 
In [6]: print(*a)
-765 -671 -730 -578 649 -620 -631 512 -764 839



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:

Python
1
2
3
4
5
6
7
In [7]: a = [randrange(-1_000, 1_000) for _ in range(100_000)]
 
In [8]: %timeit nsmallest(2, a)[-1]
7.3 ms ± 171 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
 
In [9]: %timeit sorted(a)[1]
28.1 ms ± 176 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)



0



Semen-Semenich

4611 / 3148 / 1112

Регистрация: 21.03.2016

Сообщений: 7,842

23.03.2021, 18:39

16

Цитата
Сообщение от Arsegg
Посмотреть сообщение

Прокатит, просто медленно

как?

Цитата
Сообщение от dasdads
Посмотреть сообщение

второе минимальное

кто сказал что в списке одно первое минимальное? пример (список после сортировки)

Python
1
a = [1, 1, 1, 2, 3, 4, 5, 6]

первое минимальное это 1 а второе минимальное это 2

Python
1
2
3
4
5
a = sorted([3, 4, 1, 1, 1, 2, 5, 6])
for i in a[1:]:
    if i != a[0]:
        print(i)
        break



1



3484 / 2092 / 560

Регистрация: 02.09.2015

Сообщений: 5,336

23.03.2021, 18:42

17

Цитата
Сообщение от Semen-Semenich
Посмотреть сообщение

как?

Посмотрите выше замеры timeit, если не верите — повторите. С некоторой константы использование кучи дает значительный буст в скорости.



0



AlexMarkov

99 / 86 / 20

Регистрация: 10.09.2019

Сообщений: 708

23.03.2021, 18:44

18

Мои результаты:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
In [1]: from random import randrange
 
In [2]: a = [randrange(-1_000, 1_000) for _ in range(10)]
 
In [3]: from heapq import nsmallest
 
In [4]: %timeit nsmallest(2, a)[-1]
3.17 µs ± 61.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
 
In [5]: %timeit sorted(a)[1]
347 ns ± 4.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
 
In [6]: print(*a)
523 -196 -456 989 -534 -713 506 -48 -580 853
 
In [7]: a = [randrange(-1_000, 1_000) for _ in range(100_000)]
 
In [8]: %timeit nsmallest(2, a)[-1]
4.41 ms ± 171 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
 
In [9]: %timeit sorted(a)[1]
26.9 ms ± 451 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)



0



4611 / 3148 / 1112

Регистрация: 21.03.2016

Сообщений: 7,842

23.03.2021, 18:59

19

Arsegg, мы немного не поняли друг друга. я относительно

Цитата
Сообщение от Welemir1
Посмотреть сообщение

а почему просто не sorted(a_list)[1] ?

написал что не прокатит потому что в списке может быть не один первый минимальный а не к вопросу сортировки.



0



3484 / 2092 / 560

Регистрация: 02.09.2015

Сообщений: 5,336

23.03.2021, 19:06

20

Цитата
Сообщение от Semen-Semenich
Посмотреть сообщение

написал что не прокатит потому что в списке может быть не один первый минимальный а не к вопросу сортировки.

В списке 10 элементов, как может не прокатить? Если несколько элементов подходят под условие — выводим первый.



0



IT_Exp

Эксперт

87844 / 49110 / 22898

Регистрация: 17.06.2006

Сообщений: 92,604

23.03.2021, 19:06

Помогаю со студенческими работами здесь

Найти минимальное число ходов, которые нужны шахматному коню для перехода с первого поля на второе
Даны 2 поля шахматной доски,найти минимальное число ходов, которые нужны шахматному коню для…

Найти минимальное число ходов, которые нужны шахматному коню для перехода с первого поля на второе
Ввод: input.txt
Вывод: output.txt

Даны обозначения двух полей шахматной доски…

Если первое число окажется кратным 5 или второе число будет нечетным, то вывести на экран сумму их модулей
4. Даны два числа N и М. Если первое число окажется кратным 5 или второе число будет нечетным, то…

Наименьшее число в списке, наибольшее число в списке, количество чисел в списке
Составить программу, которая получает на вход последовательность целых чисел, и печатает на экране:…

Найти минимальное число и вывести на экран число, предшествующее минимальному
С клавиатуры вводятся числа. Признак конца ввода — 0. Найти минимальное число и вывести на экран…

Число фибоначчи. Как вывести двумерный массив и найти максимальное и минимальное число
d_s segment
idw 0
masdw 20 dup (0)
d_s ends

c_s segment
assumeds:d_s, cs:c_s
begin:…

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:

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 = 0

for 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 = i

print("№%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 i
print

if arr[0] < arr[1] then
m1 = 0
m2 = 1
else
m1 = 1
m2 = 0
endif

for 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 i

print (m1+1) + ": " + arr[m1]
print (m2+1) + ": " + arr[m2]



81 7 25 71 23 9 56 91 73 64
2: 7
6: 9

Понравилась статья? Поделить с друзьями:
  • Как найти мой любимый цвет
  • Как найти прибыль фирмы совершенной конкуренции
  • Как найти потерянный телефон samsung galaxy
  • Как найти идентификатор в своем телефоне
  • Программа тренировок в тренажерном зале или как составить