23 / 21 / 3 Регистрация: 27.10.2017 Сообщений: 192 |
|
1 |
|
Найти несколько минимальных элементов в массиве16.05.2018, 19:04. Показов 6873. Ответов 13
Дан массив, в нем есть k элементов, как найти 3,4,5…n минимальных элементов в массиве? Как найти конкретное число я знаю, а как иначе — нет…
0 |
13 / 13 / 16 Регистрация: 23.04.2018 Сообщений: 110 |
|
16.05.2018, 23:55 |
2 |
nikita55050505, что? Разве минимальных может быть несколько(если только число не повторяется)?
0 |
16 / 15 / 13 Регистрация: 20.11.2017 Сообщений: 100 |
|
17.05.2018, 00:02 |
3 |
вам надо найти индексы всех минимальных элементов?
0 |
D3m1an 296 / 227 / 102 Регистрация: 11.08.2016 Сообщений: 780 |
||||
17.05.2018, 00:47 |
4 |
|||
Можно попробовать так, но есть пару нюансов. .
0 |
Eanmos 698 / 140 / 57 Регистрация: 20.08.2017 Сообщений: 255 |
||||
17.05.2018, 07:08 |
5 |
|||
Думаю, проще всего будет сначала отсортировать массив, а потом уже выводить минимальные элементы.
Вместо
0 |
woldemas 654 / 458 / 212 Регистрация: 06.09.2013 Сообщений: 1,266 |
||||
17.05.2018, 07:38 |
6 |
|||
nikita55050505
0 |
artem312312 2 / 2 / 0 Регистрация: 17.02.2017 Сообщений: 117 |
||||||||
27.05.2018, 11:22 |
7 |
|||||||
Задача состоит в том, что дан массив с консоли и нужно 1) найти k наим элементов, в пунтке 1 работает, и 2 сперва отсортировать и найти k наим элементов методом слияния и определить, что работает быстрее если в файле 1000 10000 100000 элементов, вот во 2-ом методе в данном коде сортировка работает неверно, не знаете почему? Добавлено через 12 минут
0 |
296 / 227 / 102 Регистрация: 11.08.2016 Сообщений: 780 |
|
27.05.2018, 11:30 |
8 |
artem312312,
и ещё, кто-то знает что делает эта строка? Макроопределение I . Подстановка вместо I в коде строки «(minCount == 0) ? minCount: minCount-1», что в свою очередь аналогично оператору «if» — Если minCount равен 0, то вернуть значение minCount, в противном случае вернуть minCount-1
0 |
artem312312 2 / 2 / 0 Регистрация: 17.02.2017 Сообщений: 117 |
||||||||||||
27.05.2018, 11:54 |
9 |
|||||||||||
А это? зачем тут побитовое не? и можно ли заменить?
что в свою очередь аналогично оператору «if» — Если minCount равен 0, то вернуть значение minCount, в противном случае вернуть minCount-1 Если переписать как if то оно чет не работает, ну или я не то делаю скорее всего Добавлено через 15 минут
Исправил код, теперь работает как надо, но можете прокомментировать алгоритм этой функции?
0 |
D3m1an 296 / 227 / 102 Регистрация: 11.08.2016 Сообщений: 780 |
||||
27.05.2018, 12:09 |
10 |
|||
Что значит побитовое НЕ ? Такого оператора нет.
unsigned int tmp = ~(0); //выставить все биты И собственно… выставить все биты в данном типе переменной . Инверсия 0 (~0b…0000 = 0b…1111). Добавлено через 9 минут
Программа сканирует 1 раз массив сравнивая текущее минимальное число leastDig с числом из массива. Вызывая её N раз, мы ищем N минимальных чисел из массива, не забывая отправлять предыдущее старшее число из уже найденых.
0 |
2 / 2 / 0 Регистрация: 17.02.2017 Сообщений: 117 |
|
27.05.2018, 17:35 |
11 |
Ещё небольшой вопрос, он ищет минимальные элементы правильно, но только положительных чисел, а если у меня будет -1, то не работает, как можно исправить? Добавлено через 4 часа 36 минут
Можно попробовать так, но есть пару нюансов. . Наверное ты как раз про это и говорил?
0 |
296 / 227 / 102 Регистрация: 11.08.2016 Сообщений: 780 |
|
27.05.2018, 19:03 |
12 |
artem312312, так точно.
0 |
2 / 2 / 0 Регистрация: 17.02.2017 Сообщений: 117 |
|
28.05.2018, 12:42 |
13 |
Да, отрицательные тоже нужны, но я так и не понял как их взять в диапазон Добавлено через 13 часов 20 минут Добавлено через 3 часа 12 минут
0 |
D3m1an 296 / 227 / 102 Регистрация: 11.08.2016 Сообщений: 780 |
||||
29.05.2018, 09:12 |
14 |
|||
Конечно из-за типа unsigned int. Удалять ~0 не стоит в данном случае программы. Иначе мы ничего не найдем. Этим действием мы добиваемся максимального числа. Добавлено через 1 час 51 минуту
0 |
Необходимо найти два min значения в массиве случайных числе.
Код написан под swift.
var list = [Int] ()
var n: Int = 8
for i in 1...n
{
let list = Int(arc4random_uniform(70))
print (list)
}
func getMin1Min2(numbers:Int...) -> (min1:Int, min2:Int)
{
var min1 = numbers[0]
var min2 = numbers[0]
for number in numbers
{
if number < min1 {min1 = number}
Дальше попытка найти 2-ое минимальное значение, но увы …
if number > min1
{if number < min2
{min2 = number}
}
}
return (min1, min2)
}
завершаться задача должна поиском двух мин. значений в рандомном массиве, но увы не знаю как использовать созданный массив и функцию …
var value = getMin1Min2 (list)
задан 28 мая 2016 в 18:08
1
Для начала, Вы не заполняете массив. Вот создаете массив:
let n = 8
var arr = [Int]()
for _ in 0..<n {
arr.append(Int(arc4random_uniform(70)))
}
print(arr)
Далее ищете 2 минимальных элемента в массиве, предлагаю просто отсортировать массив по возрастанию и возвращать первые 2 элемента:
func getMin1Min2(numbers:[Int]) -> (min1:Int, min2:Int){
let sortedNumbers = numbers.sort({$0 < $1})
return sortedNumbers.count > 1 ? (sortedNumbers[0], sortedNumbers[1]) : (sortedNumbers[0], sortedNumbers[0])
}
И проверка:
print(getMin1Min2(arr))
ответ дан 29 мая 2016 в 5:05
VAndrJVAndrJ
15.8k1 золотой знак18 серебряных знаков35 бронзовых знаков
Вариант 1: сделай копию массива, найди в нем минимум и удали его. Потом найди минимум еще раз.
Для не очень больших массивов подойдет.
Вариант 2: находишь первый минимум (запоминаешь его индекс).
Еще раз ищешь минимум в массиве, но уже не сравниваешь элемент с найденным индексом.
var myMin = MAX_INT
for i in 0..myArray.count {
if (myArray[i] < myMin && i != indexOfFirstMin ){
myMin = myArray[i]
}
}
Denis
8,86010 золотых знаков30 серебряных знаков55 бронзовых знаков
ответ дан 14 июн 2016 в 12:18
ВалентинВалентин
1,1056 серебряных знаков6 бронзовых знаков
0
Найти два наименьших (минимальных) элемента массива
Просмотров 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
Improve Article
Save Article
Like Article
Improve Article
Save Article
Like Article
Find the first, second and third minimum elements in an array in O(n).
Examples:
Input : 9 4 12 6 Output : First min = 4 Second min = 6 Third min = 9 Input : 4 9 1 32 12 Output : First min = 1 Second min = 4 Third min = 9
First approach : First we can use normal method that is sort the array and then print first, second and third element of the array. Time complexity of this solution is O(n Log n).
C++
#include<bits/stdc++.h>
using
namespace
std;
int
Print3Smallest(
int
array[],
int
n)
{
sort(array,array+n);
cout <<
"First min = "
<< array[0] <<
"n"
;
cout <<
"Second min = "
<< array[1] <<
"n"
;
cout <<
"Third min = "
<< array[2] <<
"n"
;
}
int
main()
{
int
array[] = {4, 9, 1, 32, 12};
int
n =
sizeof
(array) /
sizeof
(array[0]);
Print3Smallest(array, n);
return
0;
}
Java
import
java.util.Arrays;
public
class
Main {
static
void
Print3Smallest(
int
array[],
int
n) {
Arrays.sort(array);
System.out.println(
"First min = "
+ array[
0
]);
System.out.println(
"Second min = "
+ array[
1
]);
System.out.println(
"Third min = "
+ array[
2
]);
}
public
static
void
main(String[] args) {
int
array[] = {
4
,
9
,
1
,
32
,
12
};
int
n = array.length;
Print3Smallest(array, n);
}
}
Python3
def
print_3_smallest(array):
array.sort()
print
(
"First min ="
, array[
0
])
print
(
"Second min ="
, array[
1
])
print
(
"Third min ="
, array[
2
])
if
__name__
=
=
'__main__'
:
array
=
[
4
,
9
,
1
,
32
,
12
]
n
=
len
(array)
print_3_smallest(array)
C#
using
System;
using
System.Linq;
class
Program
{
static
void
Print3Smallest(
int
[] array,
int
n)
{
Array.Sort(array);
Console.WriteLine(
"First min = "
+ array[0]);
Console.WriteLine(
"Second min = "
+ array[1]);
Console.WriteLine(
"Third min = "
+ array[2]);
}
static
void
Main()
{
int
[] array = {4, 9, 1, 32, 12};
int
n = array.Length;
Print3Smallest(array, n);
}
}
Javascript
function
Print3Smallest(array,n){
array.sort((a, b) => a - b);
console.log(
'First min = '
+ array[0]);
console.log(
'Second min = '
+ array[1]);
console.log(
'Third min = '
+ array[2]);
}
let array = [4, 9, 1, 32, 12];
Print3Smallest(array,array.length);
Output
First min = 1 Second min = 4 Third min = 9
Second approach : Time complexity of this solution is O(n).
Algorithm:
- First take an element
- then if array[index] < Firstelement
- Thirdelement = Secondelement
- Secondelement = Firstelement
- Firstelement = array[index]
- else if array[index] < Secondelement
- Thirdelement = Secondelement
- Secondelement = array[index]
- else if array[index] < Thirdelement
- Thirdelement = array[index]
- then print all the element
Implementation:
C++
#include<bits/stdc++.h>
#define MAX 100000
using
namespace
std;
int
Print3Smallest(
int
array[],
int
n)
{
int
firstmin = MAX, secmin = MAX, thirdmin = MAX;
for
(
int
i = 0; i < n; i++)
{
if
(array[i] < firstmin)
{
thirdmin = secmin;
secmin = firstmin;
firstmin = array[i];
}
else
if
(array[i] < secmin)
{
thirdmin = secmin;
secmin = array[i];
}
else
if
(array[i] < thirdmin)
thirdmin = array[i];
}
cout <<
"First min = "
<< firstmin <<
"n"
;
cout <<
"Second min = "
<< secmin <<
"n"
;
cout <<
"Third min = "
<< thirdmin <<
"n"
;
}
int
main()
{
int
array[] = {4, 9, 1, 32, 12};
int
n =
sizeof
(array) /
sizeof
(array[0]);
Print3Smallest(array, n);
return
0;
}
Java
import
java.util.*;
public
class
GFG
{
static
void
Print3Smallest(
int
array[],
int
n)
{
int
firstmin = Integer.MAX_VALUE;
int
secmin = Integer.MAX_VALUE;
int
thirdmin = Integer.MAX_VALUE;
for
(
int
i =
0
; i < n; i++)
{
if
(array[i] < firstmin)
{
thirdmin = secmin;
secmin = firstmin;
firstmin = array[i];
}
else
if
(array[i] < secmin)
{
thirdmin = secmin;
secmin = array[i];
}
else
if
(array[i] < thirdmin)
thirdmin = array[i];
}
System.out.println(
"First min = "
+ firstmin );
System.out.println(
"Second min = "
+ secmin );
System.out.println(
"Third min = "
+ thirdmin );
}
public
static
void
main(String[] args)
{
int
array[] = {
4
,
9
,
1
,
32
,
12
};
int
n = array.length;
Print3Smallest(array, n);
}
}
Python3
MAX
=
100000
def
Print3Smallest(arr, n):
firstmin
=
MAX
secmin
=
MAX
thirdmin
=
MAX
for
i
in
range
(
0
, n):
if
arr[i] < firstmin:
thirdmin
=
secmin
secmin
=
firstmin
firstmin
=
arr[i]
elif
arr[i] < secmin:
thirdmin
=
secmin
secmin
=
arr[i]
elif
arr[i] < thirdmin:
thirdmin
=
arr[i]
print
(
"First min = "
, firstmin)
print
(
"Second min = "
, secmin)
print
(
"Third min = "
, thirdmin)
arr
=
[
4
,
9
,
1
,
32
,
12
]
n
=
len
(arr)
Print3Smallest(arr, n)
C#
using
System;
class
GFG
{
static
void
Print3Smallest(
int
[]array,
int
n)
{
int
firstmin =
int
.MaxValue;
int
secmin =
int
.MaxValue;
int
thirdmin =
int
.MaxValue;
for
(
int
i = 0; i < n; i++)
{
if
(array[i] < firstmin)
{
thirdmin = secmin;
secmin = firstmin;
firstmin = array[i];
}
else
if
(array[i] < secmin)
{
thirdmin = secmin;
secmin = array[i];
}
else
if
(array[i] < thirdmin)
thirdmin = array[i];
}
Console.WriteLine(
"First min = "
+ firstmin );
Console.WriteLine(
"Second min = "
+ secmin );
Console.WriteLine(
"Third min = "
+ thirdmin );
}
static
void
Main()
{
int
[]array =
new
int
[]{4, 9, 1, 32, 12};
int
n = array.Length;
Print3Smallest(array, n);
}
}
PHP
<?php
function
Print3Smallest(
$array
,
$n
)
{
$MAX
= 100000;
$firstmin
=
$MAX
;
$secmin
=
$MAX
;
$thirdmin
=
$MAX
;
for
(
$i
= 0;
$i
<
$n
;
$i
++)
{
if
(
$array
[
$i
] <
$firstmin
)
{
$thirdmin
=
$secmin
;
$secmin
=
$firstmin
;
$firstmin
=
$array
[
$i
];
}
else
if
(
$array
[
$i
] <
$secmin
)
{
$thirdmin
=
$secmin
;
$secmin
=
$array
[
$i
];
}
else
if
(
$array
[
$i
] <
$thirdmin
)
$thirdmin
=
$array
[
$i
];
}
echo
"First min = "
.
$firstmin
.
"n"
;
echo
"Second min = "
.
$secmin
.
"n"
;
echo
"Third min = "
.
$thirdmin
.
"n"
;
}
$array
=
array
(4, 9, 1, 32, 12);
$n
= sizeof(
$array
) / sizeof(
$array
[0]);
Print3Smallest(
$array
,
$n
);
?>
Javascript
<script>
let MAX = 100000
function
Print3Smallest( array, n)
{
let firstmin = MAX, secmin = MAX, thirdmin = MAX;
for
(let i = 0; i < n; i++)
{
if
(array[i] < firstmin)
{
thirdmin = secmin;
secmin = firstmin;
firstmin = array[i];
}
else
if
(array[i] < secmin)
{
thirdmin = secmin;
secmin = array[i];
}
else
if
(array[i] < thirdmin)
thirdmin = array[i];
}
document.write(
"First min = "
+ firstmin +
"</br>"
);
document.write(
"Second min = "
+ secmin +
"</br>"
);
document.write(
"Third min = "
+ thirdmin +
"</br>"
);
}
let array = [4, 9, 1, 32, 12];
let n = array.length;
Print3Smallest(array, n);
</script>
Output
First min = 1 Second min = 4 Third min = 9
Time Complexity: O(n)
Auxiliary Space: O(1)
Last Updated :
09 Mar, 2023
Like Article
Save Article
Без сортировки задача может быть решена, например, так. Создаем рабочий массив длины m и заполняем его начальными значениями. В общем случае можно в качестве такого значения выбрать минимальное значение int/integer для соответствующей среды программирования. А если известна нижняя граница значений исходного массива, то можно взять любое число, меньшее этой границы.
Итак рабочий массив заполнен одинаковыми значениями. Теперь берем элемент за элементом исходного массива и вставляем его в нужное место рабочего массива. При этом длину рабочего массива сохраняем равной m (после вставки последний элемент пропадает). Если очередной элемент меньше последнего значения рабочего массива, то он просто пропускается. Этот процесс имеет вычислительную сложность O(nm). Тогда как сортировка в лучшем случае описывается асимптотикой O(n*og(n)). Асимптотики показывают, как ведет себя функция (в данном случае — время сортировки) при стремлении параметров к бесконечности. Можно сказать, что время описанного алгоритма при стремлении n к бесконечности задается формулой t1=k1*O(n), а время сортировки t2=k2*O(n*log(n)). Здесь k1 и k2 — некие константы, зависящие от процессора, языка программирования, операционной системы и других факторов.
Я построил три системы тестов (для Питона, Java и VBA). Все тесты устроены по сути одинаково: строились массивы возрастающих размеров, заполнялись случайными числами задаваемого диапазона, сортировались с фиксацией времени и прогонялись через описанный выше алгоритм тоже с фиксацией времени. Каждый тест повторялся 10 раз и время усреднялось. В Питоне и Java использовалась встроенная сортировка, в VBA — реализация QuickSort.
Питон
Ниже показан код питоновских тестов.
import time
from random import randint
def max_n_1(arr,n):
return sorted(arr,reverse=True)[0:n]
def max_n_2(arr,n):
res=[-1 for _ in range(n)]
for x in arr:
if x > res[n-1]:
i=n-1
j=i-1
while(j>=0 and res[j]<x):
res[i]=res[j]
i=i-1
j=j-1
res[i]=x
return res
def start():
k=10
n=10000
print("k=",k)
while(n<=500000):
print("n=",n,end=' ')
t1=0.0
for i in range(10):
arr=[randint(1,2000) for _ in range(n)]
start_time = time.time()
z1=max_n_1(arr,k)
fin_time = time.time()
t1=t1+(fin_time-start_time)
print(t1/10.0,end=' ')
t2=0.0
for i in range(10):
arr=[randint(1,2000) for _ in range(n)]
start_time = time.time()
z2=max_n_2(arr,k)
fin_time = time.time()
t2=t2+(fin_time-start_time)
print(t2/10.0)
n+=10000
start()
Размеры массива менялись от 10 до 500 тыс. элементов с шагом 10 тыс. Было выполнено два прогона: определение пяти и десяти максимумов. Результат для 10 максимумов показан ниже.
Время здесь приведено в миллисекундах. Что видим? Сортировка отстает (на краю интервала — вдвое). Для пяти максимумов картина аналогична. И надо заметить, что хотя питоновская сортировка очень эффективна, простой алгоритм оказывается быстрее. Заметны резкие провалы в производительности (зубцы на графиках). Они, вероятно, объясняются влиянием внутренних процессов (типа сборки мусора). Это же замечание относится и к другим графикам.
Java
Код тестов выглядел так:
import java.util.*;
class Start
{
public static void main(String [] args)
{
Random random = new Random();
Scanner inp = new Scanner(System.in);
long startTime,endTime,tot1,tot2;
int i,a,b,n,m,x,ii,jj,u;
a=1;
b=3000; // диапазон случайных чисел [a,b]
m=10;
System.out.println(a+" "+b+" "+m);
for (n=50000; n<=5000000; n+=50000)
{
int arr[] = new int[n];
int ma[] = new int[m];
tot1=0;
for (u=0; u<10; u++)
{
for (i=0; i<n; i++)
{
arr[i]=a+random.nextInt(b-a+1);
}
startTime = System.currentTimeMillis();
Arrays.sort(arr);
endTime = System.currentTimeMillis();
tot1=tot1+(endTime-startTime);
}
tot2=0;
for (u=0; u<10; u++)
{
for (i=0; i<n; i++)
{
arr[i]=a+random.nextInt(b-a+1);
}
startTime = System.currentTimeMillis();
for (i=0; i<m; i++) ma[i]=-999999;
for (i=0; i<n; i++)
{
x=arr[i];
if (x >= ma[m-1])
{
ii=m-1;
jj=ii-1;
while(jj>=0 && ma[jj]<x)
{
ma[ii]=ma[jj];
ii--;
jj--;
}
ma[ii]=x;
}
}
endTime = System.currentTimeMillis();
tot2=tot2+(endTime-startTime);
}
System.out.println(n+" "+tot1+" "+tot2);
}
}
}
Здесь размер массива тоже менялся от 10 тыс. до 500 тыс. элементов. Время — в миллисекундах. Результат оказался весьма похожим на питоновский (только сортировка Javа, увы, медленнее).
VBA
В этом языке нет универсальной встроенной сортировки (можно, правда, сортировать ячейки листа, но в этом случае будут велики накладные расходы, связанные с загрузкой и выгрузкой данных). Поэтому пришлось реализовать QuickSort вручную. Все это выглядит так:
Private Declare Function GetTickCount Lib "kernel32" () As Long
'::: Собственно сортировка
Sub QSort(A() As Long, Optional b As Long = 1, Optional e As Long = 0)
If b > e Then Exit Sub
i& = b
j& = e
w& = A((i& + j&) / 2)
Do While (True)
Do While (A(i&) < w&)
i& = i& + 1
Loop
Do While (A(j&) > w&)
j& = j& - 1
Loop
If i& <= j& Then
Tmp& = A(i&)
A(i&) = A(j&)
A(j&) = Tmp&
i& = i& + 1
j& = j& - 1
End If
If i& > j& Then Exit Do
Loop
If j& > b Then QSort A, b, j&
If i& < e Then QSort A, i&, e
End Sub
'::: Проверка успешности сортировки
Function check(X() As Long) As Boolean
n& = UBound(X)
For i& = 1 To n& - 1
If X(i& + 1) < X(i&) Then
Debug.Print "Err! i=" + CStr(i&)
check = False
Exit Function
End If
Next i&
check = True
End Function
'::: Вставка в упорядоченный массив
Sub ins_in_arr(X As Long, A() As Long, n As Integer)
If X < A(n) Then Exit Sub
For i% = 1 To n
If X > A(i%) Then
For j% = n To i% + 1 Step -1
A(j%) = A(j% - 1)
Next j%
A(i%) = X
Exit Sub
End If
Next i%
End Sub
'::: Собственно тест
Sub test()
Const sz = 500
Dim X() As Long
Dim Ma(1 To sz) As Long
Randomize
ooo& = 1
For n& = 10000 To 500000 Step 10000
t1# = 0
For nc% = 1 To 10
ReDim X(1 To n&) As Long
For i& = 1 To n&
X(i&) = Rnd() * 5000
Next i&
s1& = GetTickCount
For i& = 1 To sz
Ma(i&) = -2147483647
Next i&
For i& = 1 To n&
ins_in_arr X(i&), Ma, 10
Next i&
s2& = GetTickCount
t1# = t1# + s2& - s1&
Next nc%
Cells(ooo&, 1).Value = n&
Cells(ooo&, 2).Value = t1# / 10
t2# = 0
For nc% = 1 To 10
ReDim X(1 To n&) As Long
For i& = 1 To n&
X(i&) = Rnd() * 5000
Next i&
s1& = GetTickCount
QSort X, 1, n&
s2& = GetTickCount
If Not check(X) Then
MsgBox "Ошибка при сортировке!"
Exit Sub
End If
t2# = t2# + s2& - s1&
Next nc%
Cells(ooo&, 3).Value = t2# / 10
ooo& = ooo& + 1
Next n&
End Sub
На каждом витке цикла корректность сортировки проверяется. Время проверки, естественно, не включается в общий хронометраж. Набор исходных данных тот же — от 10 до 500 тыс. целых чисел. Получает, в общем, похожая картина:
Представляет некоторый интерес изучить зависимость времени от количества искомых максимумов (при фиксированном размере массива). Здесь, очевидно, сортировка будет тем выгоднее, чем больше максимумов требуется найти. А вставка в упорядоченный массив будет тем медленнее, чем массив больше.
Самым невыгодным случаем будет являться, как ни странно, входной массив, уже упорядоченный по возрастанию. В этом случае количество сравнений при вставке достигнет максимума и будет равно n*m. Массив, упорядоченный по убыванию, напротив, весьма выгоден. Число сравнений здесь будет ~ m+n.
Описанный в самом начале статьи алгоритм, можно ускорить, если вместо простого упорядоченного массива использовать древовидную или пирамидальную структуру. Именно так и реализована в Питоне в модуле heapq функция nsmallest.
Для небольших массивов (несколько тысяч элементов и менее) разница в подходах представляется несущественной. И если нужно быстро написать код, то сортировка — вполне приемлемое решение. Для больших массивов выгоднее от сортировки отказаться.
Вот и все, что я хотел рассказать об этой задаче. Спасибо, что дочитали до конца. С наступившим 2021-м годом!