E121. K-ая порядковая статистика за O (N)
선택한 UI 언어에 맞게 문제 텍스트를 러시아어에서 번역합니다. 코드는 변경하지 않습니다.
Источник: e-maxx.ru/algo, страница PDF 399.
Пусть дан 배열 A длиной N и пусть given number K. 문제 заключается в том, чтобы find в этом 배열е K-ое по величине number, т.е. K-ую порядковую статистику.
Основная идея - использовать идеи 알고리즘а быстрой сортировки. Собственно, 알고리즘 несложный, сложнее доказать, что он работает в среднем за O (N), в отличие от быстрой сортировки.
구현 в виде нерекурсивной функции:
template <class T>
T order_statistics (std::vector<T> a, unsigned n, unsigned k)
{
using std::swap;
for (unsigned l=1, r=n; ; )
{
if (r <= l+1)
{
// текущая часть состоит из 1 или 2 elementов -
// легко можем find ответ
if (r == l+1 && a[r] < a[l])
swap (a[l], a[r]);
return a[k];
}
// упорядочиваем a[l], a[l+1], a[r]
unsigned mid = (l + r) >> 1;
swap (a[mid], a[l+1]);
if (a[l] > a[r])
swap (a[l], a[r]);
if (a[l+1] > a[r])
swap (a[l+1], a[r]);
if (a[l] > a[l+1])
swap (a[l], a[l+1]);
// выполняем разделение
// барьером является a[l+1], т.е. медиана среди a[l], a[l+1],
a[r]
unsigned
i = l+1,
j = r;
const T
cur = a[l+1];
for (;;)
{
while (a[++i] < cur) ;
while (a[--j] > cur) ;
if (i > j)
break;
swap (a[i], a[j]);
}
// вставляем барьер
a[l+1] = a[j];
a[j] = cur;
// продолжаем работать в той части,
// которая должна содержать искомый element
if (j >= k)
r = j-1;
if (j <= k)
l = i;
} }
Следует заметить, что в стандартной библиотеке C++ этот 알고리즘 уже реализован - он называется nth_element.
C# 해법
자동 초안, 제출 전 검토using System;
using System.Collections.Generic;
using System.Linq;
public static class AlgorithmDraft
{
// Auto-generated C# draft from the original e-maxx C/C++ listing. Review before production use.
template <class T>
T order_statistics (std::vector<T> a, unsigned n, unsigned k)
{
using std::swap;
for (unsigned l=1, r=n; ; )
{
if (r <= l+1)
{
// текущая часть состоит из 1 или 2 элементов -
// легко можем найти ответ
if (r == l+1 && a[r] < a[l])
swap (a[l], a[r]);
return a[k];
}
// упорядочиваем a[l], a[l+1], a[r]
unsigned mid = (l + r) >> 1;
swap (a[mid], a[l+1]);
if (a[l] > a[r])
swap (a[l], a[r]);
if (a[l+1] > a[r])
swap (a[l+1], a[r]);
if (a[l] > a[l+1])
swap (a[l], a[l+1]);
// выполняем разделение
// барьером является a[l+1], т.е. медиана среди a[l], a[l+1],
a[r]
unsigned
i = l+1,
j = r;
const T
cur = a[l+1];
for (;;)
{
while (a[++i] < cur) ;
while (a[--j] > cur) ;
if (i > j)
break;
swap (a[i], a[j]);
}
// вставляем барьер
a[l+1] = a[j];
a[j] = cur;
// продолжаем работать в той части,
// которая должна содержать искомый элемент
if (j >= k)
r = j-1;
if (j <= k)
l = i;
}
}
}
C++ 해법
매칭됨/원본template <class T>
T order_statistics (std::vector<T> a, unsigned n, unsigned k)
{
using std::swap;
for (unsigned l=1, r=n; ; )
{
if (r <= l+1)
{
// текущая часть состоит из 1 или 2 элементов -
// легко можем найти ответ
if (r == l+1 && a[r] < a[l])
swap (a[l], a[r]);
return a[k];
}
// упорядочиваем a[l], a[l+1], a[r]
unsigned mid = (l + r) >> 1;
swap (a[mid], a[l+1]);
if (a[l] > a[r])
swap (a[l], a[r]);
if (a[l+1] > a[r])
swap (a[l+1], a[r]);
if (a[l] > a[l+1])
swap (a[l], a[l+1]);
// выполняем разделение
// барьером является a[l+1], т.е. медиана среди a[l], a[l+1],
a[r]
unsigned
i = l+1,
j = r;
const T
cur = a[l+1];
for (;;)
{
while (a[++i] < cur) ;
while (a[--j] > cur) ;
if (i > j)
break;
swap (a[i], a[j]);
}
// вставляем барьер
a[l+1] = a[j];
a[j] = cur;
// продолжаем работать в той части,
// которая должна содержать искомый элемент
if (j >= k)
r = j-1;
if (j <= k)
l = i;
}
}
Java 해법
자동 초안, 제출 전 검토import java.util.*;
import java.math.*;
public class AlgorithmDraft {
// Auto-generated Java draft from the original e-maxx C/C++ listing. Review before production use.
template <class T>
T order_statistics (std::vector<T> a, unsigned n, unsigned k)
{
using std::swap;
for (unsigned l=1, r=n; ; )
{
if (r <= l+1)
{
// текущая часть состоит из 1 или 2 элементов -
// легко можем найти ответ
if (r == l+1 && a[r] < a[l])
swap (a[l], a[r]);
return a[k];
}
// упорядочиваем a[l], a[l+1], a[r]
unsigned mid = (l + r) >> 1;
swap (a[mid], a[l+1]);
if (a[l] > a[r])
swap (a[l], a[r]);
if (a[l+1] > a[r])
swap (a[l+1], a[r]);
if (a[l] > a[l+1])
swap (a[l], a[l+1]);
// выполняем разделение
// барьером является a[l+1], т.е. медиана среди a[l], a[l+1],
a[r]
unsigned
i = l+1,
j = r;
const T
cur = a[l+1];
for (;;)
{
while (a[++i] < cur) ;
while (a[--j] > cur) ;
if (i > j)
break;
swap (a[i], a[j]);
}
// вставляем барьер
a[l+1] = a[j];
a[j] = cur;
// продолжаем работать в той части,
// которая должна содержать искомый элемент
if (j >= k)
r = j-1;
if (j <= k)
l = i;
}
}
}
Материал разбит как 알고리즘ическая 문제: изучить постановку, понять асимптотику и реализовать 알고리즘 на выбранном языке.
Vacancies for this task
활성 채용 with overlapping task tags are 표시됨.
아직 활성 채용이 없습니다.