How to sort an array with n elements in which k elements are out of place in O(n + k log k)?

大城市里の小女人 提交于 2021-01-04 06:44:04

问题


I was asked this in an interview today, and am starting to believe it is not solvable.

Given a sorted array of size n, select k elements in the array, and reshuffle them back into the array, resulting in a new "nk-sorted" array.

Find the k (or less) elements that have moved in that new array.

Here is (Python) code that creates such arrays, but I don't care about language for this.

import numpy as np


def __generate_unsorted_array(size, is_integer=False, max_int_value=100000):
    return np.random.randint(max_int_value, size=size) if is_integer else np.random.rand(size)


def generate_nk_unsorted_array(n, k, is_integer=False, max_int_value=100000):
    assert k <= n
    unsorted_n_array = __generate_unsorted_array(n - k, is_integer, max_int_value=max_int_value)
    sorted_n_array = sorted(unsorted_n_array)
    random_k_array = __generate_unsorted_array(k, is_integer, max_int_value=max_int_value)
    insertion_inds = np.random.choice(n - k + 1, k, replace=True)  # can put two unsorted next to each other.
    nk_unsorted_array = np.insert(sorted_n_array, insertion_inds, random_k_array)
    return list(nk_unsorted_array)

Is this doable under the complexity constraint?

This is only part of the question. The whole question required to sort the "nk-sorted array" in O(n+klogk)


回答1:


This sorts a nk-unsorted array in O(n + klogk), assuming the array should be ascending.

  1. Find elements which are not sorted by traversing the array.
  2. If such an element was found (it is larger then the following one), then either it or the following one are out of order (or both).
  3. Keep both of them aside, and remove them from the array
  4. continue traversing on the newly obtained array (after removal), form the index which comes before the found element.
  5. This will put aside 2k elements in O(n) time.
  6. Sort 2k elements O(klogk)
  7. Merge two sorted lists which have total n elements, O(n)
  8. Total O(n + klogk)

Code:

def merge_sorted_lists(la, lb):
    if la is None or la == []:
        return lb
    if lb is None or lb == []:
        return la
    a_ind = b_ind = 0
    a_len = len(la)
    b_len = len(lb)

    merged = []
    while a_ind < a_len and b_ind < b_len:
        a_value = la[a_ind]
        b_value = lb[b_ind]

        if a_value < b_value:
            merged.append(la[a_ind])
            a_ind += 1
        else:
            merged.append(lb[b_ind])
            b_ind += 1

    # get the leftovers into merged
    while a_ind < a_len:
        merged.append(la[a_ind])
        a_ind += 1
    while b_ind < b_len:
        merged.append(lb[b_ind])
        b_ind += 1

    return merged

and

def sort_nk_unsorted_list(nk_unsorted_list):
    working_copy = nk_unsorted_list.copy()  # just for ease of testing

    requires_resorting = []

    current_list_length = len(working_copy)
    i = 0
    while i < current_list_length - 1 and 1 < current_list_length:
        if i == -1:
            i = 0

        first = working_copy[i]
        second = working_copy[i + 1]

        if second < first:
            requires_resorting.append(first)
            requires_resorting.append(second)

            del working_copy[i + 1]
            del working_copy[i]
            i -= 2
            current_list_length -= 2
        i += 1

    sorted_2k_elements = sorted(requires_resorting)
    sorted_nk_list = merge_sorted_lists(sorted_2k_elements, working_copy)
    return sorted_nk_list


来源:https://stackoverflow.com/questions/62764861/how-to-sort-an-array-with-n-elements-in-which-k-elements-are-out-of-place-in-on

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!