#c #c #algorithm
#c #c #алгоритм
Вопрос:
Есть ли способ за линейное время, с помощью которого мы можем найти, какой элемент массива является вторым по величине? Элементы массива могут быть положительными, отрицательными или нулевыми. Элементы могут повторяться. STLS не допускаются. Можно использовать Python.
Решение: Отсортируйте массив и возьмите второй элемент, но сортировка не разрешена
Модификация: По определению вторым по величине элементом будет тот, который численно меньше. Например, если у нас есть
Arr = {5,5,4,3,1}, Тогда второй по величине элемент равен 4
Дополнение Допустим, если я хочу обобщить вопрос до k-го по величине и сложности, меньшей линейной, как nlogn, каким может быть решение.
Комментарии:
1. Почему в линейном времени, когда вы можете получить его за
n long n
время?2. Если максимальное значение дублируется, считается ли оно вторым по величине значением или мы должны выбрать то, которое находится под ним? То есть в списке
3,4,5,5
находится4
или5
второй по величине элемент?3. 4 считается вторым по величине элементом.
4. @user1344784 пожалуйста, предложите, как это можно сделать в
n logn
благодарность.5. @Codeanu
O(n) < O(n long n)
Ответ №1:
Пройдите по массиву, сохранив 2 слота памяти для записи 2 самых больших элементов, замеченных на данный момент. Верните меньший из двух.
…. есть ли что-нибудь сложное в этом вопросе, чего я не вижу?
Комментарии:
1. Если это действительно тот же алгоритм, что и Simone, он также завершится неудачей, если первые два элемента будут иметь одинаковое значение и максимальное значение.
2. Если список содержит три элемента {0, 1, 1}, какой элемент является вторым по величине? Он по-прежнему равен 1. Попробуйте отсортировать такой список и взять второй элемент сверху.
3. Я думаю, это зависит от определения второго по величине тогда. Я добавил комментарий и удалил свой отрицательный отзыв.
4. @bdares допустим, если я хочу обобщить вопрос до k-го по величине, этот алгоритм может оказаться неподходящим.
5. @Codeanu, тогда да, quickselect, безусловно, правильный путь. Но это не то, что вы спрашивали изначально. Я подумал как о quickselect, так и об этом методе, когда увидел вопрос, но если вам действительно нужен только 2-й по величине (или около того), то это гораздо более простая в реализации вещь, чем quickselect .
Ответ №2:
Вы можете, это псевдоалгоритм:
max = 2max = SMALLEST_INT_VALUE;
for element in v:
if element > max:
2max = max;
max = element;
else if element > 2max:
2max = element;
2max — это искомое значение.
Алгоритм не вернет правильное значение для конкретных случаев, таких как массив, где его элементы равны.
Комментарии:
1. Я не думаю, что вам нужно менять местами … 2max = max достаточно, поскольку вы перезаписываете max в следующей строке. кроме того, во второй строке вы предполагаете, что v[1] < v[0]: вероятно, вам следует это исправить…
2. Ошибка заключается в том, что первые два элемента имеют одинаковое значение и максимальное значение в списке.
3. Вы правы. AFAICS, инициализации обоих наименьшим целочисленным значением, которое можно было ожидать, должно быть достаточно, не так ли?
Ответ №3:
Если вам нужен истинный алгоритм O (n) и вы хотите найти n-й по величине элемент в массиве, тогда вам следует использовать quickselect (по сути, это быстрая сортировка, при которой вы удаляете раздел, который вас не интересует), и ниже приведена отличная запись с анализом времени выполнения:
Комментарии:
1. @Codeanu: Рад, что ты знаешь, что это помогает тебе
2. Ссылка в ответе, похоже, разорвана. Вот статья в wiki об алгоритме quickselect: en.wikipedia.org/wiki/Quickselect
3. Кроме того, quickselect — это не O (n); это O (n ^ 2), потому что он имеет низкую производительность в наихудшем случае. Далее используется алгоритм сортировки, но в вопросе говорится, что сортировка запрещена, поэтому это похоже на нарушение ограничений проблемы.
Ответ №4:
Псевдокод:
int max[2] = { array[0], array[1] }
if(max[1] < max[0]) swap them
for (int i = 2; i < array.length(); i ) {
if(array[i] >= max[0]) max[1] = max[0]; max[0] = array[i]
else if(array[i] >= max[1]) max[1] = array[i];
}
Теперь максимальный массив содержит максимум 2 элемента.
Комментарии:
1. Вы не проверяете, какой из array[0] и array[1] больше.
2. Тайлер Кромптон, да, вы правы. Я забыл упомянуть об этом. Я сделаю это прямо сейчас!
Ответ №5:
- создайте временный массив размером 3,
- скопируйте туда первые 3 элемента,
- сортировка временного массива,
- замените последний элемент во временном массиве на 4-й элемент из исходного массива,
- сортировка временного массива,
- замените последний элемент во временном массиве на 5-й элемент из исходного массива,
- сортировка временного массива,
- и т.д.
Сортировка массива размером 3 — это постоянное время, и вы делаете это один раз для каждого элемента исходного массива, следовательно, общее линейное время.
Комментарии:
1. Линейное время требует больших затрат, но действительно линейно. Следует упомянуть, что вы хотите выполнять сортировку в порядке убывания , если вы хотите постоянно заменять последний элемент. Будет ли это также зависеть от выбора max, если есть повторяющиеся значения max (в зависимости от того, считается ли дубликат максимальным).
Ответ №6:
Да. Вы пометили это как C / C , но упомянули, что можете сделать это на Python. В любом случае, вот алгоритм:
- Создайте массив (очевидно).
- Если первый элемент больше второго элемента, задайте первой переменной значение первого элемента, а второй переменной — значение второго элемента. В противном случае, сделайте наоборот.
- Перебирайте все элементы (кроме первых двух).
- Если элемент из массива больше первой переменной, задайте второй переменной значение first variable, а первой переменной значение item. Иначе, если элемент больше второй переменной, задайте для элемента вторую переменную.
Вторая переменная — это ваш ответ.
list = [-1,6,9,2,0,2,8,10,8,-10]
if list[0] > list[1]:
first = list[0]
second = list[1]
else:
first = list[1]
second = list[0]
for i in range(2, len(list)):
if list[i] > first:
first, second = list[i], first
elif list[i] > second:
second = list[i]
print("First:", first)
print("Second:", second)
Ответ №7:
// assuming that v is the array and length is its length
int m1 = max(v[0], v[1]), m2 = min(v[0], v[1]);
for (int i=2; i<length; i ) {
if (likely(m2 >= v[i]))
continue;
if (unlikely(m1 < v[i]))
m2 = m1, m1 = v[i];
else
m2 = v[i];
}
Нужный вам результат выражен в m2 (вероятные и маловероятные макросы определены как здесь в целях повышения производительности, вы можете просто удалить их, если они вам не нужны).
Ответ №8:
Я думаю, что другие ответы не учитывали тот факт, что в массиве типа [0, 1, 1] вторым по величине является 0 (согласно обновленному определению проблемы). Кроме того, все упоминания о quickselect относятся не к O (n), а скорее к O (n ^ 2) и выполняют гораздо больше работы, чем необходимо (помимо этого, это алгоритм сортировки, который не разрешен в постановке задачи). Вот алгоритм, очень похожий на алгоритм Simone, но обновленный для возврата второго по величине уникального элемента:
def find_second(numbers):
top = numbers[0]
second = None
for num in numbers[1:]:
if second is None:
if num < top: second = num
elif num > top:
second = top
top = num
else:
if num > second:
if num > top:
second = top
top = num
elif num < top: second = num
if second is not None: return second
return top
if __name__ == '__main__':
print "The second largest is %d" % find_second([1,2,3,4,4,5,5])
Ответ №9:
// Second larger element and its position(s)
int[] tab = { 12, 1, 21, 12, 8, 8, 1 };
int[] tmp = Arrays.copyOf(tab, tab.length);
int secMax = 0;
Arrays.sort(tmp);
secMax = tmp[tmp.length - 2];
System.out.println(secMax);
List<Integer> positions = new ArrayList<>();
for (int i = 0; i < tab.length; i ) {
if (tab[i] == secMax) {
positions.add(i);
}
}
System.out.println(positions);