Given an array arr[], where each element is at most k positions away from its correct position in the sorted order. Your task is to restore the sorted order of arr[] by rearranging the elements in place.
Examples:Â
Input: arr[]= [2, 3, 1, 4], k = 2Â
Output: [1, 2, 3, 4]
Explanation: All elements are at most k = 2 positions away from their correct positions.
Element 1 moves from index 2 to 0
Element 2 moves from index 0 to 1
Element 3 moves from index 1 to 2
Element 4 stays at index 3.Input:Â arr[]= [1, 4, 5, 2, 3, 6, 7, 8, 9, 10], k = 2
Output: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Explanation: The sorted array will be 1 2 3 4 5 6 7 8 9 10.
Table of Content
[Naive Approach] Sorting - O(n log(n)) Time and O(1) Space
The idea is to sort the given array in ascending order using any sorting algorithm.
Working of Approach:
- Directly sort the given array using the built-in sort() function.
- The array is rearranged in ascending order.
#include
#include
#include
using namespace std;
void nearlySorted(vector<int> &arr, int k)
{
// directly sort the array
sort(arr.begin(), arr.end());
}
int main()
{
vector<int> arr = {2, 3, 1, 4};
int k = 2;
nearlySorted(arr, k);
cout << "[";
for (int i = 0; i < arr.size(); i++)
{
cout << arr[i];
if (i != arr.size() - 1)
cout << ", ";
}
cout << "]";
return 0;
}
import java.util.Arrays;
import java.util.Collections;
public class GFG {
public static void nearlySorted(int[] arr, int k)
{
// directly sort the array
Arrays.sort(arr);
}
public static void main(String[] args)
{
int[] arr = { 2, 3, 1, 4 };
int k = 2;
nearlySorted(arr, k);
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
if (i != arr.length - 1)
System.out.print(", ");
}
System.out.print("]");
}
}
def nearlySorted(arr, k):
# directly sort the array
arr.sort()
if __name__ == "__main__":
arr = [2, 3, 1, 4]
k = 2
nearlySorted(arr, k)
print('[', end='')
for i in range(len(arr)):
print(arr[i], end='')
if i!= len(arr) - 1:
print(', ', end='')
print(']')
using System;
public class GFG {
public static void nearlySorted(int[] arr, int k)
{
// directly sort the array
Array.Sort(arr);
}
public static void Main()
{
int[] arr = { 2, 3, 1, 4 };
int k = 2;
nearlySorted(arr, k);
Console.Write("[");
for (int i = 0; i < arr.Length; i++) {
Console.Write(arr[i]);
if (i != arr.Length - 1)
Console.Write(", ");
}
Console.Write("]");
}
}
function nearlySorted(arr, k)
{
// directly sort the array
arr.sort((a, b) => a - b);
}
// Driver Code
const arr = [ 2, 3, 1, 4 ];
const k = 2;
nearlySorted(arr, k);
console.log("[" + arr.join(", ") + "]");
Output
[1, 2, 3, 4]
Note: This approach might get accepted on online judges, but it ignores the given constraint, so it is not suitable for real interview scenarios where an optimized solution is expected.
[Expected Approach] Heap - O(n * log k) Time and O(k) Space
As given in the question, the element at index i could be anywhere between i - k and i + k in the sorted array. If we start placing the correct elements from left to right, then the element for the current position must be within the next k+1 elements, and we don’t need to check the elements to the left..
We use a min-heap to store the next k + 1 possible elements. Since every element is at most k positions away from its correct position, the minimum element in the heap can be placed at the current position.
Working of Approach:
- Insert the first k elements into a min-heap.
- Insert the next element into the heap and remove the minimum element.
- Place the removed minimum element at the current index.
- Repeat this process until all elements are processed.
- Finally, place the remaining elements from the heap into the array.
Let us understand with an example:
Input: arr[]= [2, 3, 1, 4], k = 2Â
- Insert 2, 3 into the min-heap. Then insert 1, remove 1, and place it at index 0.
- Insert 4 into the heap, remove the minimum 2, and place it at index 1.
- The heap now contains 3, 4. Remove 3 and place it at index 2.
- Remove the remaining 4 and place it at index 3.
- The final array is [1, 2, 3, 4].
#include
#include
#include
#include
using namespace std;
void nearlySorted(vector<int> &arr, int k)
{
int n = arr.size();
// creating a min heap
priority_queue<int, vector<int>, greater<int>> pq;
// pushing first k elements in pq
for (int i = 0; i < k; i++)
pq.push(arr[i]);
int i;
for (i = k; i < n; i++)
{
pq.push(arr[i]);
// size becomes k+1 so pop it
// and add minimum element in (i-k) index
arr[i - k] = pq.top();
pq.pop();
}
// puting remaining elements in array
while (!pq.empty())
{
arr[i - k] = pq.top();
pq.pop();
i++;
}
}
int main()
{
vector<int> arr = {2, 3, 1, 4};
int k = 2;
nearlySorted(arr, k);
cout << "[";
for (int i = 0; i < arr.size(); i++)
{
cout << arr[i];
if (i != arr.size() - 1)
cout << ", ";
}
cout << "]";
return 0;
}
import java.util.PriorityQueue;
public class GFG {
public static void nearlySorted(int[] arr, int k)
{
int n = arr.length;
// creating a min heap
PriorityQueue<Integer> pq = new PriorityQueue<>();
// pushing first k elements in pq
for (int i = 0; i < k; i++)
pq.add(arr[i]);
int i;
for (i = k; i < n; i++) {
pq.add(arr[i]);
// size becomes k+1 so pop it
// and add minimum element in (i-k) index
arr[i - k] = pq.peek();
pq.poll();
}
// putting remaining elements in array
while (!pq.isEmpty()) {
arr[i - k] = pq.peek();
pq.poll();
i++;
}
}
public static void main(String[] args)
{
int[] arr = { 2, 3, 1, 4 };
int k = 2;
nearlySorted(arr, k);
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
if (i != arr.length - 1)
System.out.print(", ");
}
System.out.print("]");
}
}
import heapq
def nearlySorted(arr, k):
n = len(arr)
# Creating a min heap
pq = []
# Pushing first k elements in pq
for i in range(k):
heapq.heappush(pq, arr[i])
# Process remaining elements
for i in range(k, n):
heapq.heappush(pq, arr[i])
# Size becomes k + 1 so pop it
# and add minimum element at (i - k) index
arr[i - k] = heapq.heappop(pq)
# After the loop, i is n - 1 in Python.
# Move to the next index.
i = n
# Putting remaining elements in array
while pq:
arr[i - k] = heapq.heappop(pq)
i += 1
if __name__ == '__main__':
arr = [2, 3, 1, 4]
k = 2
nearlySorted(arr, k)
print('[', end='')
for i in range(len(arr)):
print(arr[i], end='')
if i != len(arr) - 1:
print(', ', end='')
print(']')
using System;
class GFG {
class MinHeap {
private int[] heap;
private int size;
public MinHeap(int capacity)
{
heap = new int[capacity];
size = 0;
}
public void Push(int value)
{
int i = size;
heap[size++] = value;
while (i > 0) {
int parent = (i - 1) / 2;
if (heap[parent] <= heap[i])
break;
int temp = heap[parent];
heap[parent] = heap[i];
heap[i] = temp;
i = parent;
}
}
public int Pop()
{
int result = heap[0];
heap[0] = heap[size - 1];
size--;
int i = 0;
while (true) {
int left = 2 * i + 1;
int right = 2 * i + 2;
int smallest = i;
if (left < size
&& heap[left] < heap[smallest])
smallest = left;
if (right < size
&& heap[right] < heap[smallest])
smallest = right;
if (smallest == i)
break;
int temp = heap[i];
heap[i] = heap[smallest];
heap[smallest] = temp;
i = smallest;
}
return result;
}
public bool IsEmpty() { return size == 0; }
}
public void nearlySorted(int[] arr, int k)
{
int n = arr.Length;
MinHeap pq = new MinHeap(k + 1);
// Pushing first k elements in heap
for (int j = 0; j < k; j++)
pq.Push(arr[j]);
int i;
for (i = k; i < n; i++) {
pq.Push(arr[i]);
// Size becomes k + 1, so pop minimum
// and add it at (i - k) index
arr[i - k] = pq.Pop();
}
// Putting remaining elements in array
while (!pq.IsEmpty()) {
arr[i - k] = pq.Pop();
i++;
}
}
static void Main()
{
int[] arr = { 2, 3, 1, 4 };
int k = 2;
GFG obj = new GFG();
obj.nearlySorted(arr, k);
Console.Write("[");
for (int i = 0; i < arr.Length; i++) {
Console.Write(arr[i]);
if (i != arr.Length - 1)
Console.Write(", ");
}
Console.Write("]");
}
}
function push(heap, val)
{
heap.push(val);
let i = heap.length - 1;
while (i > 0) {
let parent = Math.floor((i - 1) / 2);
if (heap[parent] <= heap[i])
break;
[heap[parent], heap[i]] = [ heap[i], heap[parent] ];
i = parent;
}
}
function pop(heap)
{
let min = heap[0];
heap[0] = heap[heap.length - 1];
heap.pop();
let i = 0;
while (true) {
let left = 2 * i + 1;
let right = 2 * i + 2;
let smallest = i;
if (left < heap.length
&& heap[left] < heap[smallest])
smallest = left;
if (right < heap.length
&& heap[right] < heap[smallest])
smallest = right;
if (smallest === i)
break;
[heap[i], heap[smallest]] =
[ heap[smallest], heap[i] ];
i = smallest;
}
return min;
}
function nearlySorted(arr, k)
{
let n = arr.length;
let pq = [];
// Push first k elements
for (let i = 0; i < k; i++)
push(pq, arr[i]);
let index = 0;
// Process remaining elements
for (let i = k; i < n; i++) {
push(pq, arr[i]);
// Put minimum element at its correct position
arr[index] = pop(pq);
index++;
}
// Put remaining elements in the array
while (pq.length > 0)
arr[index++] = pop(pq);
}
// Driver Code
let arr = [ 2, 3, 1, 4 ];
let k = 2;
nearlySorted(arr, k);
console.log(arr);
Output
[1, 2, 3, 4]