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++
void insertionSort( int A[], int size)
{
int i, key, j;
for (i = 1; i < size; i++)
{
key = A[i];
j = i - 1;
while (j >= 0 && A[j] > key)
{
A[j + 1] = A[j];
j = j - 1;
}
A[j + 1] = key;
}
}
|
C
void insertionSort( int A[], int size)
{
int i, key, j;
for (i = 1; i < size; i++)
{
key = A[i];
j = i-1;
while (j >= 0 && A[j] > key)
{
A[j+1] = A[j];
j = j-1;
}
A[j+1] = key;
}
}
|
Java
static void insertionSort( int A[], int size)
{
int i, key, j;
for (i = 1 ; i < size; i++)
{
key = A[i];
j = i- 1 ;
while (j >= 0 && A[j] > key)
{
A[j+ 1 ] = A[j];
j = j- 1 ;
}
A[j+ 1 ] = key;
}
}
|
Python3
def insertionSort(A, size):
i, key, j = 0 , 0 , 0
for i in range (size):
key = A[i]
j = i - 1
while j > = 0 and A[j] > key:
A[j + 1 ] = A[j]
j = j - 1
A[j + 1 ] = key
|
C#
static void insertionSort( int A[], int size)
{
int i, key, j;
for (i = 1; i < size; i++) {
key = A[i];
j = i - 1;
while (j >= 0 && A[j] > key) {
A[j + 1] = A[j];
j = j - 1;
}
A[j + 1] = key;
}
}
|
Javascript
function insertionSort(A, size)
{
var i, key, j;
for (i = 1; i < size; i++)
{
key = A[i];
j = i-1;
while (j >= 0 && A[j] > key)
{
A[j+1] = A[j];
j = j-1;
}
A[j+1] = key;
}
}
|

Time Complexity: O(nk), 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.
Auxiliary Space: O(1)
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). We are creating heap of size k as the element can be atmost k distance from its index in a sorted array.
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 log k time. So overall complexity will be O(k) + O((n-k) * log(k)).
C++
#include <bits/stdc++.h>
using namespace std;
void sortK( int arr[], int n, int k)
{
int size;
size=(n==k)?k:k+1;
priority_queue< int , vector< int >, greater< int > > pq(arr, arr +size);
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();
}
}
void printArray( int arr[], int size)
{
for ( int i = 0; i < size; i++)
cout << arr[i] << " " ;
cout << endl;
}
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;
}
|
Java
import java.util.Iterator;
import java.util.PriorityQueue;
class GFG {
private static void kSort( int [] arr, int n, int k)
{
if (arr == null || arr.length == 0 ) {
return ;
}
PriorityQueue<Integer> priorityQueue
= new PriorityQueue<>();
int minCount = Math.min(arr.length, k + 1 );
for ( int i = 0 ; i < minCount; 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();
}
}
private static void printArray( int [] arr, int n)
{
for ( int i = 0 ; i < n; i++)
System.out.print(arr[i] + " " );
}
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);
}
}
|
Python3
from heapq import heappop, heappush, heapify
def print_array(arr: list ):
for elem in arr:
print (elem, end = ' ' )
def sort_k(arr: list , n: int , k: int ):
heap = arr[:k + 1 ]
heapify(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
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)
|
C#
using System;
using System.Collections.Generic;
class GFG {
static void kSort( int [] arr, int n, int k)
{
List< int > priorityQueue = new List< int >();
for ( int i = 0; i < k + 1; i++) {
priorityQueue.Add(arr[i]);
}
priorityQueue.Sort();
int index = 0;
for ( int i = k + 1; i < n; i++) {
arr[index++] = priorityQueue[0];
priorityQueue.RemoveAt(0);
priorityQueue.Add(arr[i]);
priorityQueue.Sort();
}
int queue_size = priorityQueue.Count;
for ( int i = 0; i < queue_size; i++) {
arr[index++] = priorityQueue[0];
priorityQueue.RemoveAt(0);
}
}
static void printArray( int [] arr, int n)
{
for ( int i = 0; i < n; i++)
Console.Write(arr[i] + " " );
}
static void Main()
{
int k = 3;
int [] arr = { 2, 6, 3, 12, 56, 8 };
int n = arr.Length;
kSort(arr, n, k);
Console.WriteLine( "Following is sorted array" );
printArray(arr, n);
}
}
|
Javascript
<script>
function kSort(arr,n,k)
{
let priorityQueue=[];
for (let i = 0; i < k + 1; i++) {
priorityQueue.push(arr[i]);
}
priorityQueue.sort( function (a,b){ return a-b;});
let index = 0;
for (let i = k + 1; i < n; i++) {
arr[index++] = priorityQueue[0];
priorityQueue.shift();
priorityQueue.push(arr[i]);
priorityQueue.sort( function (a,b){ return a-b;});
}
while (priorityQueue.length != 0) {
arr[index++] = priorityQueue[0];
priorityQueue.shift();
}
}
function printArray(arr,n)
{
for (let i = 0; i < n; i++)
document.write(arr[i] + " " );
}
let k = 3;
let arr = [ 2, 6, 3, 12, 56, 8 ];
let n = arr.length;
kSort(arr, n, k);
document.write( "Following is sorted array<br>" );
printArray(arr, n);
</script>
|
OutputFollowing is sorted array
2 3 6 8 12 56
Time Complexity: O(k) + O((m) * log(k)) , where m = n – k
Auxiliary Space: O(k)
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(log k) time. So Balanced BST based method will also take O(n log k) time, but the Heap based 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.