Пару дней назад я столкнулся с проблемой, в которой меня попросили найти n-й наименьший элемент в массиве. Это было отмечено как проблема среднего уровня, и это быстро заставило меня задуматься, почему это так сложно??? Просто отсортируйте массив, а затем верните значение, которое присутствует в индексе…
// This is assuming the nthSmallestIndex is within the array. public int getNthSmallestElement(int[] array, int nthSmallestIndex) { Arrays.sort(array); return array[nthSmallestIndex]; }
Приведенный выше код кажется довольно элементарным, так почему же это проблема среднего уровня? Что ж, на мой вопрос ответили довольно скоро. Когда я запустил код, онлайн-редактор пожаловался, что мой код работает медленно. Для сортировки массива, диапазон которого полностью неизвестен, быстрее всего это можно сделать в O(n log n). Вопрос требовал, чтобы я завершил код за O (n) время.
Затем мне пришло в голову, что мне не нужно сортировать весь массив. Мне нужно только отсортировать массив до n-го наименьшего индекса. Так если у меня есть следующий массив [5, 2, 1, 4, 6, 3], и если мне нужно найти 2-е наименьшее число, мне просто нужно отсортировать первые 3 элемента.
Ну, я мог бы использовать раздел lomuto , чтобы выбрать элемент поворота и поместить его в правильный индекс и изменить порядок массива, где все элементы, меньшие, чем ось, находятся слева, а большие элементы справа. Давайте посмотрим, как реализован раздел lomuto.
public int lomutoPartition(int low, int high, int[] array) { int pivot = array[high], j = low; for (int i = low; i < high; i++) { if (array[i] < pivot) { int temp = array[i]; array[i] = array[j]; array[j] = temp; ++j; } } int temp = array[high]; array[high] = array[j]; array[j] = temp; return j; }
Поэтому, если у меня есть приведенный выше массив, и если я применю раздел lomuto, сохранив последний элемент в качестве стержня, я могу получить что-то вроде этого… [2, 1, 3, 6, 4, 5]. Обратите внимание, что 3 находится в нужном месте, а все элементы слева меньше 3, а элементы справа больше 3.
Теперь все, что мне нужно проверить, это то, что n-й наименьший индекс больше или меньше текущего значения, а затем продолжайте сортировать массив, пока я не достигну требуемого индекса. Затем меня осенило, что это быстрая сортировка с небольшой модификацией!!! Давайте взглянем на код…
public int getNthSmallestElement(int[] array, int nthSmallestIndex, int low, int high) { if (low < high) { int pivot = lomutoPartition(low, high, array); if (pivot == nthSmallestIndex) { return array[nthSmallestIndex]; } if (nthSmallestIndex > pivot) { return getNthSmallestElement(array, nthSmallestIndex, pivot + 1, high); } return getNthSmallestElement(array, nthSmallestIndex, low, pivot - 1); } return -1; }
Теперь это решение в среднем случае получает n-й наименьший элемент за O (n) время. Позже, когда я выполнял поиск в Google, я обнаружил, что вышеупомянутое решение называется “Быстрый выбор”.
Я надеюсь, что этот пост помог вам понять, как найти n-й наименьший элемент за O (n) время (средний случай).)
Если вы хотите увидеть полную реализацию и другие подобные вопросы, ознакомьтесь с моим Репо на github.
Оригинал: “https://dev.to/vineeth/find-the-nth-smallest-element-in-an-array-2eam”