Алгоритм для поиска высоких/низких чисел с максимальным сравнением 1.5n
Я уже подумывал об этом домашнем задании. Учитывая числовой массив размером n, создайте алгоритм, который будет находить высокие и низкие значения с максимальным сравнением 1.5n.
Моя первая попытка была
int high=0
int low= Number.MaxValue //problem statement is unclear on what type of number to use
Number numList[0 . . n] //number array, assuming unsorted
for (i=0, i < n, i++) {
if (numList[i] > high)
high = numList[i]
else if (numList[i] < low)
low = numList[i]
}
Моя проблема заключается в том, что каждая итерация цикла имеет одну из трех возможностей:
- найдено низкое значение - сделано 1 сравнение.
- найдено высокое значение - сделано 2 сравнения.
- не найдено - сделано 2 сравнения.
Таким образом, для всего обхода массива можно сделать максимум 2n сравнений, что далеко от максимальной потребности в 1,5,1 сравнениях.
Ответы
Ответ 1
Начните с пар чисел и найдите локальные минимальные и максимальные значения (n/2 сравнения). Затем найдите глобальный максимум из n/2 локальных maxes (n/2 сравнения) и аналогично глобальный min из локальных mins (n /2 сравнения). Всего сравнений: 3 * n/2!
For i in 0 to n/2: #n/2 comparisons
if x[2*i]>x[2*i+1]:
swap(x,2*i,2*i+1)
global_min = min( x[0], x[2], ...) # n/2 comparisons
global_max = max( x[1], x[3], ...) # n/2 comparisons
Обратите внимание, что указанное решение изменяет массив. Альтернативное решение:
Initialize min and max
For i = 0 to n/2:
if x[2*i]<x[2*i+1]:
if x[2*i]< min:
min = x[2*i]
if x[2*i+1]> max:
max = x[2*i+1]
else:
if x[2*i+1]< min:
min = x[2*i+1]
if x[2*i]> max:
max = x[2*i]
Ответ 2
Я знаю, что это уже ответили, но на случай, если кто-то ищет другой способ подумать об этом. Этот ответ похож на Lester's, но может обрабатывать нечетные значения n без нарушения и будет по-прежнему проводить максимум 1.5n сравнений. Секрет в модуле.;)
В качестве побочного эффекта обеспечения того, чтобы мы поместили последнее значение в соответствующий подвой массив, второй элемент в данном листе будет сравниваться и помещаться дважды. Однако, поскольку мы не меняем исходный массив, и нас интересует только высокий и низкий набор, это не имеет особого значения.
Initialize lowArray and highArray
Initialize subArrayCounter to 0
For i = 0; i < n; i+=2
X = givenList[i];
Y = givenList[(i+1)%n];
If(x < y)
lowArray[subArrayCounter] = x;
highArray[subArrayCounter] = y;
subArrayCounter++;
else
lowArray[subArrayCounter] = y;
highArray[subArrayCounter] = x;
subArrayCounter++;
Initialize low to lowArray[0];
Initialize high to highArray[0];
For i = 1; i < lowArray.length; i++
If(lowArray[i] < low)
Low = lowArray[i];
For i = 1; i < highArray.length; i++
If(highArray[i] > high)
High = highArray[i]
Ответ 3
Это тот же ответ, что и ElKamina, но поскольку я уже начал писать псевдокод, я думал, что закончу и опубликую его.
Идея состоит в том, чтобы сравнить пары значений (n/2 сравнения), чтобы получить массив с высокими значениями и массив с низкими значениями. С каждым из этих массивов мы снова сравниваем пары значений (сравнения 2 * n/2) для получения наивысших и наименьших значений соответственно.
n/2 + 2*n/2 = 1.5n comparisons
Здесь псевдокод:
int[] highNumList;
int[] lowNumList;
for (i = 0, i < n, i+=2)
{
a = numList[i];
b = numList[i+1];
if (a > b)
{
highNumList.Add(a);
lowNumlist.Add(b);
}
else
{
highNumlist.Add(b);
lowNumList.Add(a);
}
}
int high = highNumList[0];
int low = lowNumList[0];
for (i = 0, i < n/2, i+=2)
{
if (highNumList[i] < highNumList[i+1])
high = highNumList[i+1]
if (lowNumList[i] > lowNumList[i+1])
low = lowNumList[i+1]
}
Этот код не учитывает, что n
не является четным, или исходный массив пуст.
Ответ 4
Это вопрос, который у меня был во время интервью, и я нашел ответ с небольшим намеком от интервьюера, который был "Как вы сравниваете два числа?" (это действительно помогло).
Вот объяснение:
Допустим, у меня есть 100 чисел (вы можете легко заменить его на n, но он лучше работает для примера, если n - четное число). Что я делаю, так это то, что я разделил его на 50 списков из 2-х чисел. Для каждой пары я делаю одно сравнение, и я сделан (что составляет 50 сравнений к настоящему времени), тогда мне просто нужно найти минимум минимумов (это 49 сравнений) и максимум максимумов (что также 49 сравнений), так что мы должны сделать сравнения 49 + 49 + 50 = 148. Мы закончили!
Примечание. Чтобы найти минимум, действуем следующим образом (в псевдокоде):
n=myList.size();
min=myList[0];
for (int i(1);i<n-1;i++)
{
if (min>myList[i]) min=myList[i];
}
return min;
И мы находим это в (n-1) сравнениях. Код почти одинаковый для максимума.