Sort a nearly sorted (or K sorted) array

Given an array of n elements, where each element is at most k away from its target position, devise an algorithm that sorts in O(n log k) time. For example, let us consider k is 2, an element at index 7 in the sorted array, can be at indexes 5, 6, 7, 8, 9 in the given array.

Examples:

Input : arr[] = {6, 5, 3, 2, 8, 10, 9}
            k = 3 
Output : arr[] = {2, 3, 5, 6, 8, 9, 10}

Input : arr[] = {10, 9, 8, 7, 4, 70, 60, 50}
         k = 4
Output : arr[] = {4, 7, 8, 9, 10, 50, 60, 70}


We can use Insertion Sort to sort the elements efficiently. Following is the C code for standard Insertion Sort.

C

filter_none

edit
close

play_arrow

link
brightness_4
code

/* Function to sort an array using insertion sort*/
void insertionSort(int A[], int size)
{
   int i, key, j;
   for (i = 1; i < size; i++)
   {
       key = A[i];
       j = i-1;
  
       /* Move elements of A[0..i-1], that are greater than key, to one 
          position ahead of their current position.
          This loop will run at most k times */
       while (j >= 0 && A[j] > key)
       {
           A[j+1] = A[j];
           j = j-1;
       }
       A[j+1] = key;
   }
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

/* Function to sort an array using insertion sort*/
static void insertionSort(int A[], int size) 
int i, key, j; 
for (i = 1; i < size; i++) 
    key = A[i]; 
    j = i-1
  
    /* Move elements of A[0..i-1], that are greater than key, to one 
        position ahead of their current position. 
        This loop will run at most k times */
    while (j >= 0 && A[j] > key) 
    
        A[j+1] = A[j]; 
        j = j-1
    
    A[j+1] = key; 

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Function to sort an array using
# insertion sort
def insertionSort(A, size):
i, key, j = 0, 0, 0
for i in range(size):
    key = A[i] 
    j = i-1
  
    # Move elements of A[0..i-1], that are 
    # greater than key, to one position 
    # ahead of their current position. 
    # This loop will run at most k times 
    while j >= 0 and A[j] > key:
        A[j + 1] = A[j] 
        j = j - 1
    A[j + 1] = key

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

/* C# Function to sort an array using insertion sort*/
static void insertionSort(int A[], int size) 
    int i, key, j; 
        for (i = 1; i < size; i++) 
        
            key = A[i]; 
            j = i-1; 
  
    /* Move elements of A[0..i-1], that are greater than key, to one 
        position ahead of their current position. 
        This loop will run at most k times */
    while (j >= 0 && A[j] > key) 
    
        A[j+1] = A[j]; 
        j = j-1; 
    
    A[j+1] = key; 

chevron_right



The inner loop will run at most k times. To move every element to its correct place, at most k elements need to be moved. So overall complexity will be O(nk)

We can sort such arrays more efficiently with the help of Heap data structure. Following is the detailed process that uses Heap.
1) Create a Min Heap of size k+1 with first k+1 elements. This will take O(k) time (See this GFact)
2) One by one remove min element from heap, put it in result array, and add a new element to heap from remaining elements.

Removing an element and adding a new element to min heap will take Logk time. So overall complexity will be O(k) + O((n-k)*logK)

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// A STL based C++ program to sort a nearly sorted array.
#include <bits/stdc++.h>
using namespace std;
   
// Given an array of size n, where every element
// is k away from its target position, sorts the
// array in O(nLogk) time.
int sortK(int arr[], int n, int k)
{
    // Insert first k+1 items in a priority queue (or min heap)
    //(A O(k) operation). We assume, k < n.
    priority_queue<int, vector<int>, greater<int> > pq(arr, arr + k + 1);
   
    // i is index for remaining elements in arr[] and index
    // is target index of for current minimum element in
    // Min Heapm 'hp'.
    int index = 0;
    for (int i = k + 1; i < n; i++) {
        arr[index++] = pq.top();
        pq.pop();
        pq.push(arr[i]);
    }
   
    while (pq.empty() == false) {
        arr[index++] = pq.top();
        pq.pop();
    }
}
   
// A utility function to print array elements
void printArray(int arr[], int size)
{
    for (int i = 0; i < size; i++)
        cout << arr[i] << " ";
    cout << endl;
}
   
// Driver program to test above functions
int main()
{
    int k = 3;
    int arr[] = { 2, 6, 3, 12, 56, 8 };
    int n = sizeof(arr) / sizeof(arr[0]);
    sortK(arr, n, k);
   
    cout << "Following is sorted array" << endl;
    printArray(arr, n);
   
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// A java program to sort a nearly sorted array
import java.util.Iterator;
import java.util.PriorityQueue;
  
class GFG 
{
    private static void kSort(int[] arr, int n, int k) 
    {
  
        // min heap
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
  
        // add first k + 1 items to the min heap
        for(int i = 0; i < k + 1; i++)
        {
            priorityQueue.add(arr[i]);
        }
  
        int index = 0;
        for(int i = k + 1; i < n; i++) 
        {
            arr[index++] = priorityQueue.peek();
            priorityQueue.poll();
            priorityQueue.add(arr[i]);
        }
  
        Iterator<Integer> itr = priorityQueue.iterator();
  
        while(itr.hasNext()) 
        {
            arr[index++] = priorityQueue.peek();
            priorityQueue.poll();
        }
  
    }
  
    // A utility function to print the array
    private static void printArray(int[] arr, int n) 
    {
        for(int i = 0; i < n; i++)
            System.out.print(arr[i] + " ");
    }
  
    // Driver Code
    public static void main(String[] args) 
    {
        int k = 3;
        int arr[] = { 2, 6, 3, 12, 56, 8 };
        int n = arr.length;
        kSort(arr, n, k);
        System.out.println("Following is sorted array");
        printArray(arr, n);
    }
}
  
// This code is contributed by 
// Manpreet Singh(manpreetsngh294)

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# A Python3 program to sort a
# nearly sorted array.
  
from heapq import heappop, heappush, heapify
  
  
# A utility function to print 
# array elements
def print_array(arr: list):
    for elem in arr:
        print(elem, end = ' ')
  
# Given an array of size n, where every  
# element is k away from its target 
# position, sorts the array in O(nLogk) time.
def sort_k(arr: list, n: int, k: int):
    """
    :param arr: input array
    :param n: length of the array
    :param k: max distance, which every 
     element is away from its target position.
    :return: None
    """
    # List of first k+1 items
    heap = arr[:k + 1]
  
    # using heapify to convert list 
    # into heap(or min heap)
    heapify(heap)
  
    # "rem_elmnts_index" is index for remaining 
    # elements in arr and "target_index" is 
    # target index of for current minimum element 
    # in Min Heap "heap".
    target_index = 0
    for rem_elmnts_index in range(k + 1, n):
        arr[target_index] = heappop(heap)
        heappush(heap, arr[rem_elmnts_index])
        target_index += 1
  
    while heap:
        arr[target_index] = heappop(heap)
        target_index += 1
  
# Driver Code
k = 3
arr = [2, 6, 3, 12, 56, 8]
n = len(arr)
sort_k(arr, n, k)
  
print('Following is sorted array')
print_array(arr)
  
# This code is contributed by 
# Veerat Beri(viratberi)

chevron_right



Output:

Following is sorted array
2 3 6 8 12 56

The Min Heap based method takes O(nLogk) time and uses O(k) auxiliary space.

We can also use a Balanced Binary Search Tree instead of Heap to store K+1 elements. The insert and delete operations on Balanced BST also take O(Logk) time. So Balanced BST based method will also take O(nLogk) time, but the Heap bassed method seems to be more efficient as the minimum element will always be at root. Also, Heap doesn’t need extra space for left and right pointers.

Please write comments if you find any of the above codes/algorithms incorrect, or find other ways to solve the same problem.



My Personal Notes arrow_drop_up