Check if an Array Is Sorted
Дан массив целых чисел nums. Верните true, если он упорядочен по неубыванию, то есть каждый элемент меньше или равен следующему за ним, и false в противном случае. Равные соседние элементы допустимы: [2, 2, 3] считается отсортированным массивом. Массив из одного элемента отсортирован.
Функция
- numsinteger-array
- массив целых чисел для проверки
- Возвращаетboolean
- true, если каждый элемент не больше следующего, иначе false
Ограничения
1 ≤ nums.length ≤ 5000-109 ≤ nums[i] ≤ 109
Примеры
- Ввод
- nums = [1, 3, 3, 7]
- Вывод
- true
- Пояснение
- Каждый шаг идет вверх или остается на том же уровне: от 1 до 3, от 3 до 3, от 3 до 7. Повторение 3 допустимо, поэтому ответ —
true.
- Ввод
- nums = [2, 5, 4, 9]
- Вывод
- false
- Пояснение
- Шаг от 5 к 4 направлен вниз. Одного такого шага достаточно, чтобы массив стал неотсортированным, хотя 9 в конце — наибольшее значение, поэтому ответ —
false.
+16 скрытых тестов при отправке
Дополнительный вопрос
Как бы вы проверили массив, который может быть отсортирован в любом порядке — по возрастанию или по убыванию, — всё ещё за один проход?
Подсказки
Открывайте по одной. Каждая подсказывает чуть больше.
Если массив не отсортирован, где это можно увидеть? Нужно ли сравнивать элементы, которые находятся далеко друг от друга?
Достаточно сравнить каждый элемент со следующим за ним. Одинаковые соседние элементы допустимы; порядок нарушает только убывание.
Переберите соседние пары и верните
falseдля первой пары, в которой левое значение больше правого. Если такой пары нет, вернитеtrue.
Решение
Массив отсортирован, если ни один элемент не больше следующего за ним. Вам никогда не нужно сравнивать элементы, расположенные далеко друг от друга: если каждая соседняя пара упорядочена, то упорядочен и весь массив. Поэтому достаточно за один проход проверить n-1 пар и остановиться при первом нарушении порядка.
Отсортируйте копию и сравните
Идея
Отсортированный массив — это массив, который не изменится после сортировки. Поэтому создайте копию nums, отсортируйте её и проверьте, совпадает ли она с исходным массивом позиция за позицией. Если совпадают все позиции, значит, nums уже был упорядочен.
Для [2, 5, 4, 9] отсортированная копия будет [2, 4, 5, 9]. В позиции 1 в исходном массиве находится 5, а в копии — 4, поэтому ответ — false. Для [1, 3, 3, 7] копия идентична исходному массиву, поэтому ответ — true.
Это решение правильное, но оно делает больше, чем требуется в задаче. Сортировка требует O(n log n) операций — около 6 × 10^4 сравнений для 5000 чисел, а для копии требуется O(n) памяти. Кроме того, оно всегда просматривает весь массив, даже если уже первая пара не упорядочена.
Алгоритм
- Скопируй
nums, чтобы исходный список остался неизменным. - Отсортируй копию по возрастанию чисел.
- Сравни копию с
numsпо каждой позиции. - Верни
true, если совпадают все позиции, иначеfalse.
def isSorted(nums):
# sorted returns a new list, so nums itself is left as it was.
return sorted(nums) == numsСравните каждую пару соседей
Идея
Вам не нужна отсортированная версия, чтобы узнать, отсортирован ли массив. Массив упорядочен по неубыванию тогда и только тогда, когда каждый элемент не больше следующего за ним. Поскольку цепочки неравенств ≤ выполняются (a ≤ b и b ≤ c дают a ≤ c), проверки n-1 соседних пар достаточно, чтобы охватить все пары позиций.
Переберите i от 1 до n-1 и сравните nums[i-1] с nums[i]. Для [2, 5, 4, 9] пара (2, 5) подходит, а в паре (5, 4) порядок нарушается, поэтому сразу верните false, не проверяя 9. Равные соседние элементы подходят, потому что условие нарушается только при >.
Каждая пара сравнивается один раз, поэтому время выполнения составляет O(n), а единственная дополнительная память — это индекс цикла, O(1). Сравнивайте два значения напрямую, а не вычитайте одно из другого: при значениях до 10^9 разность может привести к переполнению 32-битного int.
Алгоритм
- Выполняй цикл с
iот 1 доn-1. - Если
nums[i-1] > nums[i], верниfalse. - Если цикл завершится, верни
true. Для одного элемента цикл пропускается, и массив отсортирован.
def isSorted(nums):
for i in range(1, len(nums)):
# One step down anywhere breaks the order.
if nums[i - 1] > nums[i]:
return False
return True
Ловушки и крайние случаи
Цикл короткий, поэтому ошибки возникают на его границах и в условии сравнения.
- Считать равных соседей нарушением порядка. Проверка
nums[i-1] >= nums[i]отклоняет[1, 3, 3, 7]. Порядок нарушает только строгое убывание (>). - Выход за конец массива. Цикл от
0доn-1, который сравниваетnums[i]сnums[i+1], должен останавливаться на одну итерацию раньше, иначе он обращается за пределы массива. Начало сi = 1и сравнение сi-1позволяют избежать этой проблемы. - Вычитать вместо сравнения. Выражение
nums[i] - nums[i-1] >= 0выглядит так же, но10^9 - (-10^9) = 2 × 10^9не помещается в 32-битное целое число и переполняется до отрицательного значения, поэтому[-1000000000, 1000000000]определяется как неотсортированный массив. Такое же переполнение нарушает работу компаратора qsort, записанного какx - y. - Сортировать числа как текст. В JavaScript вызов
sort()без функции сравнения ставит10перед9, поэтому проверка сортировкой и сравнением дает неверные результаты.
Частые вопросы4
Как проверить, отсортирован ли массив?
Сравни каждый элемент со следующим. Если какой-либо элемент больше своего правого соседа, массив не отсортирован, и можно остановиться; если ты дойдёшь до конца, не найдя такого элемента, значит, он отсортирован. Это занимает O(n) времени и O(1) дополнительной памяти.
Почему достаточно проверять соседей?
Отношение порядка транзитивно: если a ≤ b и b ≤ c, то a ≤ c. Поэтому, если каждая соседняя пара расположена в порядке, то и любая пара позиций расположена в порядке. И наоборот, в любом неотсортированном массиве есть хотя бы одна соседняя пара, в которой значение уменьшается.
Отсортирован ли массив с одинаковыми элементами?
Да, в неубывающем порядке: [4, 4, 4] отсортирован, потому что ни один элемент не больше следующего. Если в задаче требуется строгий возрастающий порядок, измените проверку так, чтобы она также отклоняла равные соседние элементы.
Могу ли я отсортировать копию и сравнить её с оригиналом?
Да, и он дает правильный ответ, но требует времени O(n log n) и дополнительной памяти O(n) для копии. Проверка соседних элементов работает быстрее, не требует копии и может вернуть результат при первом шаге вниз, не читая остальные элементы.
Похожие задачи
Задачи на те же идеи. Решите две или три, и приём запомнится.
Python
def isSorted(nums):
# Напишите код здесьСлучай 1
Случай 2
Ввод
nums = [1, 3, 3, 7]
Ожидается
true