Как найти медиану m отсортированных массивов?

Как найти медиану M отсортированных массивов целых чисел? Где размер каждого массива ограничен N. Предположим, что каждый массив содержит отсортированные целые элементы.

Есть два варианта этого вопроса.

  1. Каждый массив имеет одинаковый размер.
  2. Каждый массив имеет разный размер.

person rgaut    schedule 31.08.2014    source источник
comment
Итак, вы ищете единственную медиану конкатенации m отсортированных массивов? что ты уже испробовал?   -  person Teepeemm    schedule 01.09.2014
comment
Что такое m sorted array?   -  person Nir Alfasi    schedule 01.09.2014
comment
@teepeemm Прошу прощения за плохую формулировку. Я обновил вопросы. Я попытался расширить алгоритм медианы двух отсортированных массивов разного размера. Но до особой сложности не дошел.   -  person rgaut    schedule 01.09.2014
comment
@alfasin Есть M отсортированных массивов, каждый массив содержит целочисленные элементы. Надеюсь, теперь это ясно.   -  person rgaut    schedule 01.09.2014
comment
Это все еще не говорит нам о том, что вы пробовали до сих пор.   -  person beaker    schedule 01.09.2014
comment
@beaker: см. мой комментарий в ответе Shankhoneer ниже.   -  person rgaut    schedule 01.09.2014
comment
возможный дубликат медианы 5 отсортированных массивов   -  person Hesham Attia    schedule 25.12.2014


Ответы (2)


Я просто дам подсказку, так как вы не упомянули, что вы пробовали:

1. Create a min heap (MIN-HEAPIFY) using all the 0-th element of the m arrays
2. Extract min and add an element into the heap from the array from which the min was extracted
3. Assuming all m arrays are of n length EXTRACT-MIN from heap till you get m*n/2 elements.

Попробуйте доказать, как работает это решение, и придумайте код.

person Shankhoneer Chakrovarty    schedule 01.09.2014
comment
Я думал, что тот же ответ, но сложность в таком случае: Создание кучи O (M) + извлечение элементов MN/2 из кучи вызовет сложность MNlogM, поэтому общая сложность будет O (MNlogM). Я ищу что-то лучше. - person rgaut; 01.09.2014
comment
Извлечение одного минимального элемента из кучи будет O(lgM), поэтому извлечение n/2 элемента будет O(NlgM). Ссылка: Введение в алгоритмы Cormen et al. Глава Heapsort, алгоритм HEAP-EXTRACT-MAX - person Shankhoneer Chakrovarty; 03.09.2014
comment
Хммм Сколько элементов вы извлекаете из кучи??? МН/2 правильно? Вам нужно вызвать Extract-MIN MN раз, и каждый вызов будет стоить logM, поэтому в сумме это будет MNlogM. - person rgaut; 04.09.2014
comment
Да, вы правы, я принял N за весь размер ввода, тогда как N на самом деле является размером одного массива. Если вам нужен алгоритм лучше этого, вам нужно выполнить бинарный поиск. Я обновлю сообщение с кодом и подойду позже сегодня вечером. - person Shankhoneer Chakrovarty; 04.09.2014
comment
@ShankhoneerChakrovarty, где твой ответ? - person Pythoner; 02.05.2018
comment
@Pythoner Вопрос является дубликатом медианы 5 отсортированных массивов, поэтому я не стал опубликуйте ответ здесь. Верхний ответ на этот вопрос решает проблему, полностью заботясь обо всех крайних случаях. - person Shankhoneer Chakrovarty; 09.05.2018
comment
Лимит времени превышен. - person Charlie 木匠; 27.11.2018

Java-версия

public class Solution {
    /**
     * @param nums: the given k sorted arrays
     * @return: the median of the given k sorted arrays
     */
    public double findMedian(int[][] nums) {
        int n = getTotal(nums);
        if (n == 0) {
            return 0;
        }

        if (n % 2 != 0) {
            return findKth(nums, n / 2 + 1);
        }

        return (findKth(nums, n / 2) + findKth(nums, n / 2 + 1)) / 2.0;
    }

    private int getTotal(int[][] nums) {
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i].length;
        }
        return sum;
    }

    // k is not zero-based, it starts from 1.
    private int findKth(int[][] nums, int k) {
        int start = 0, end = Integer.MAX_VALUE;

        // find the last number x that >= k numbers are >= x. 
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (getGTE(nums, mid) >= k) {
                start = mid;
            } else {
                end = mid;
            }
        }

        if (getGTE(nums, start) >= k) {
            return start;
        }

        return end;
    }

    // get how many numbers greater than or equal to val in 2d array
    private int getGTE(int[][] nums, int val) {
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += getGTE(nums[i], val);
        }
        return sum;
    }

    // get how many numbers greater than or equal to val in an array
    private int getGTE(int[] nums, int val) {
        if (nums == null || nums.length == 0) {
            return 0;
        }

        int start = 0, end = nums.length - 1;

        // find first element >= val 
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (nums[mid] >= val) {
                end = mid;
            } else {
                start = mid;
            }
        }

        if (nums[start] >= val) {
            return nums.length - start;
        }

        if (nums[end] >= val) {
            return nums.length - end;
        }

        return 0;
    }
    }
person Pythoner    schedule 02.05.2018