K-й самый маленький элемент и K-й элемент? - PullRequest
1 голос
/ 22 марта 2019

Меня действительно смущает, в чем именно разница между самым маленьким элементом K и элементом Kth.

Элемент Kth = элемент kth это массив = массив [k-1]

, но чтоk-й самый маленький элемент?У меня вопрос на домашнюю работу, где мне нужно написать алгоритм, чтобы найти k-й наименьший элемент в 2 отсортированных массивах.Я здесь не для того, чтобы просить вас сделать мою домашнюю работу, вам не нужно давать мне какой-либо алгоритм или код.Все, что я хочу, это понять, что означает k-й наименьший элемент.В чем разница между самым маленьким элементом K и элементом kth.

Причина, по которой я спросил это, заключается в следующем: я гуглю, что такое kth самый маленький элемент, один из веб-сайтов:

For example if A = [10, 20, 40, 60] and B =[15, 35, 50, 70, 100] and K = 4 
then solution should be 35 because union of above arrays will be C = 
[10,15,20,35,40,50,60,70,100] and fourth smallest element is 35.

Этоточно так же, как k-й элемент массива.AUB [k-1] - это ответ.

Другой пример:

A = [3, 5, 9, 15, 27, 33, 35, 41, 57, 65]
B = [1, 16, 18, 42, 44, 46, 48, 50, 52, 54]

AUB = [1, 3, 5, 9, 15, 16, 18, 27, 33, 35, 41, 42, 44, 46, 48, 50, 52, 54, 57, 65]
and if k = 6
then AUB[6-1] = 16;
if k = 8
then AUB[8-1] = 27;

Я прав?Есть ли исключение, что k-й наименьший элемент отсутствует в AUB [k-1]?Если да, можете ли вы привести пример и объяснить?

Редактировать: я только что видел, как кто-то сказал, что k-й наименьший элемент - это массив [k-1] в порядке возрастания.

Iзадал вопрос моему учителю:

Когда мы говорим о k-м элементе, это на [k] или [k-1]

Его ответ:

ЧитатьПостановка проблемы тщательно.Выходные данные должны быть k-м наименьшим элементом среди 2n элементов в SU T. Эти выходные данные не обязательно имеют индекс k любого из этих списков.Почему это должно быть?

Я не понимаю. Вывод не обязательно по индексу k любого из списков? Что это значит?

Ответы [ 4 ]

1 голос
/ 22 марта 2019

Выходные данные не обязательно находятся в индексе k одного из списков? Что это значит?

Это означает, что вы должны решить проблему, не создавая C, aka AUB.

Вместо этого вы должны выполнять итерацию обоих массивов параллельно, пока не найдете k-й наименьший элемент.

Псевд логика:

Ai = 0, Bi = 0
Loop K-1 times:
    if A[Ai] < B[Bi] then Ai++ else Bi++
kth smallest = min(A[Ai], B[Bi])

Пример

A = [10, 20, 40, 60], B =[15, 35, 50, 70, 100], K = 4

Ai = 0, Bi = 0: A[0] < B[0] so Ai++
Ai = 1, Bi = 0: A[1] > B[0] so Bi++
Ai = 1, Bi = 1: A[1] < B[1] so Ai++
Ai = 2, Bi = 1: min(A[2], B[1]) = 35

4-е наименьшее значение равно 35, найдено в B[1].

Как видно, выходные данные не имеют индекс 3(= 4-1) любого списка.


K-й наименьший элемент и K-й элемент?

И поскольку вы никогда не создаете комбинированный список, а вместо этого работаетенепосредственно в двух разных списках нет элемента Kth, поэтому вопрос, поставленный в заголовке, не имеет смысла.

1 голос
/ 22 марта 2019

Как вы уже указали, объединение двух массивов будет тем, что вы ищете. Итак, вот пример:

S = [0,4,5,7]
T = [1,2,8,9]
then A = S v T = [0,1,2,4,5,7,8,9]

Теперь, когда вы посмотрите в этот массив, вы обнаружите, что k-й элемент имеет индекс k-1. Это потому, что мы, как правило, начинаем считать с one и выше. Итак, мы говорим первый элемент и имеем в виду элемент с индексом 0.

Следуя этому, это также ответ на ваш другой вопрос. Поскольку у вас есть два массива, наименьшее k-е число будет на A[k-1], но ваш учитель имел в виду, что в любом из этих массивов S и T они могут быть не по индексу k-1 , В приведенном выше примере 5-е наименьшее число - 5 с индексом 4 из A, но это третий элемент в S или S[2].

0 голосов
/ 25 марта 2019

Как уже говорили другие, K-й наименьший элемент - arr[k], после сортировки по возрастанию.

Это также известно как Алгоритм выбора , и самый известный алгоритм для случайного входного массива: Быстрый выбор , выполняется за O(n) время, которое тесно связано с Быстрая сортировка .

Я недавно написал реализацию, вы можете взглянуть.


код - в Java

QuickSelect.java

/**
 * Find k-th smallest element from an array, via quick select.
 *
 * @author eric
 * @date 3/24/19 3:49 PM
 */
public class QuickSelect {
    /**
     * Find k-th smallest element, of given array.
     *
     * @param arr input array, will be modified (sorted partially),
     * @param k   k-th, start from 0,
     * @return index of k-th, in the array,
     */
    public static int findKth(int[] arr, int k) {
        if (k < 0 || k >= arr.length)
            throw new IllegalArgumentException("array length = " + arr.length + ", thus k should < " + arr.length + ", but get: " + k);
        return findKth(arr, k, 0, arr.length - 1);
    }

    /**
     * Find k-th smallest element, of given sub array.
     *
     * @param arr   input array, will be modified (sorted partially),
     * @param k     k-th, start from 0,
     * @param start inclusive
     * @param end   inclusive
     * @return index of k-th, in the array,
     */
    public static int findKth(int[] arr, int k, int start, int end) {
        if (start == end && start == k) return k; // base case,
        int pvt = end; // index of pivot, initially taken from last element of sub array,

        // check each element in sub array,
        for (int i = start; i <= end; i++) {
            if (i < pvt && arr[i] > arr[pvt]) { // on left of pivot, and it's larger,
                if (pvt - i == 1) { // neighbor, just switch,
                    int tmp = arr[i];
                    arr[i] = arr[pvt];
                    arr[pvt] = tmp;
                } else { // not neighbor,
                    // swap 3 positions,
                    int tmp = arr[i];
                    arr[i] = arr[pvt - 1];
                    arr[pvt - 1] = arr[pvt];
                    arr[pvt] = tmp;

                    pvt -= 1; // adjust pvt,

                    i--; // restart from i,
                }
            } else if (i > pvt && arr[i] < arr[pvt]) { // on right of pivot, and it's smaller,
                if (i - pvt == 1) { // neighbor, just switch,
                    int tmp = arr[i];
                    arr[i] = arr[pvt];
                    arr[pvt] = tmp;
                } else {
                    // swap 3 positions,
                    int tmp = arr[i];
                    arr[i] = arr[pvt + 1];
                    arr[pvt + 1] = arr[pvt];
                    arr[pvt] = tmp;

                    pvt += 1; // adjust pvt,
                    // continue from i+1;
                }
            }
        }

        int leftSize = pvt - start; // element count on left side of pivot, in sub array,
        if (leftSize == k) { // pivot itself is k-th,
            return pvt;
        } else if (leftSize > k) {
            return findKth(arr, k, start, pvt - 1); // find on left part,
        } else {
            return findKth(arr, k - leftSize - 1, pvt + 1, end); // find on right part,
        }
    }
}

QuickSelectTest.java
(контрольный пример, через TestNG)

import eric.algorithm.dynamic.ShufflePerfectly;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.util.Arrays;

/**
 * QuickSelect test.
 *
 * @author eric
 * @date 3/24/19 3:50 PM
 */
public class QuickSelectTest {
    private int size = 20; // array size, should be even,
    private int[] arr; // array with unique elements,
    private int[] arrDup; // array with duplicated elements,

    @BeforeMethod
    private void setUp() {
        // init - arr,
        arr = new int[size];
        for (int i = 0; i < size; i++) arr[i] = i;
        ShufflePerfectly.shuffle(arr); // shuffle,
        // System.out.printf("[initial] arr = %s\n", Arrays.toString(arr));

        // init - arrDup,
        arrDup = new int[size];
        int halfIdx = size / 2;
        for (int i = 0; i < halfIdx; i++) {
            arrDup[i] = i;
            arrDup[i + halfIdx] = i;
        }
        ShufflePerfectly.shuffle(arrDup); // shuffle,
        // System.out.printf("[initial] arrDup = %s\n", Arrays.toString(arrDup));
    }

    @Test
    public void test() {
        System.out.printf("\n[initial]: arr = %s\n", Arrays.toString(arr));

        for (int i = 0; i < arr.length; i++) {
            // setUp(); // re-random array,
            int idx = QuickSelect.findKth(arr, i);

            Assert.assertEquals(idx, i); // check index,
            Assert.assertEquals(arr[idx], i); // check value,
            System.out.printf("[after %d-th]: arr = %s\n", i, Arrays.toString(arr));
        }
    }

    @Test
    public void test_dup() {
        System.out.printf("\n[initial]: arrDup = %s\n", Arrays.toString(arrDup));

        for (int i = 0; i < arr.length; i++) {
            // setUp(); // re-random array,
            int idx = QuickSelect.findKth(arrDup, i);

            Assert.assertEquals(idx, i); // check index,
            Assert.assertEquals(arrDup[idx], i / 2); // check value,
            System.out.printf("[after %d-th]: arrDup = %s\n", i, Arrays.toString(arrDup));
        }
    }

    @Test(expectedExceptions = IllegalArgumentException.class)
    public void test_invalid_outOfRange() {
        QuickSelect.findKth(arr, arr.length);
    }

    @Test(expectedExceptions = IllegalArgumentException.class)
    public void test_invalid_negative() {
        QuickSelect.findKth(arr, -1);
    }
}

Советы:

  • Он изменит входной массив, если не будет сделана копия.
  • Поддерживается дублирование элементов.
  • Код предназначен для понимания алгоритма, а не для производства.
    Для производства, возможно, нужно выбрать стержень более случайно, я не уверен.

Для вашего исходного ввода

Поскольку вы получили 2 отсортированный массив , приведенный выше алгоритм не является обязательным.

Вы можете просто выполнить цикл по 2 массивам в одном цикле с одним указателем на каждый массив и добавить указатель с меньшим значением на 1 на каждом шаге, пока общий шаг не станет k.

0 голосов
/ 22 марта 2019

Объединение двух массивов - это просто массив, содержащий все элементы обоих массивов.

Например, A[1,20,40,70] and B[10,50,60,80] Объединение двух вышеупомянутых массивов может быть C[1,20,40,70,10,50,60,80]

. Теперь предположим, что диапазон k начинается с 1 (включительно), предположим, что k = 3, теперь k-й элемент равен 40, ноk-й наименьший элемент - 20.

Метод, позволяющий сделать это эффективно, заключается в том, как вы подходите к этому.Один (не слишком эффективный) подход может состоять в том, чтобы просто использовать k вложенных итераций и найти k-й наименьший элемент из несортированного массива объединения.

Другим подходом может быть сортировка массива после получения объединения, другой способ - просто объединить два массива так, чтобы результирующее объединение было отсортировано (сортировка слиянием: процедура слияния).В таком случае результирующий массив будет иметь k-й наименьший элемент, такой же, как k-й элемент.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...