Given an array arr[], partition the array by assuming last element as pivot element.
The partition of an array must satisfy the following two conditions:
- Elements smaller than the pivot element appear before pivot in the array.
- Elements larger than or equal to the pivot element appear after pivot it in the array.
Note: There might me more than one possible partition arrays.
Examples:
Input: arr[] = [5, 13, 6, 9, 12, 11, 8]
Output: [5, 6, 8, 13, 9, 12, 11]
Explanation: All elements smaller than pivot element [5, 6] were arranged before it and elements larger than pivot [13, 9, 12, 11] were arranged after it.Input: arr[] = [4, 10, 9, 16, 19, 9]
Output: [4, 9, 9, 10, 16, 19]
Explanation: All elements smaller than pivot element [4] were arranged before it and elements larger than or equal to pivot [9, 10, 16, 19] were arranged after it.
Table of Content
Lomuto Algorithm for Array Partition O(n) Time and O(1) Space
The Lomuto partition algorithm divides an array based on a pivot element. One pointer marks the boundary for elements smaller than the pivot, while the other pointer helps in array traversal. As we traverse the array, smaller elements are moved to the left of the boundary and boundary expands. After the traversal, all elements to the left of the boundary are smaller, and those on the right are larger than pivot.
Step-by-step explanation of algorithm:
- Choose the last element of the array as the pivot.
- Initialize pointer i at the start; it represents the boundary of elements strictly smaller than the pivot.
- Traverse the array using pointer j from start to second last element:
- If arr[j] < pivot, swap arr[i] and arr[j], then increment i.
- After traversal, all elements smaller than the pivot are on the left side of index i.
- Swap arr[i] with the pivot to place the pivot at its correct position.
- Final state: Left of pivot → elements < pivot, Right of pivot → elements ≥ pivot
- Note: Elements equal to the pivot may appear on the right side, which contributes to QuickSort being unstable.
#include <iostream>
#include <vector>
using namespace std;
void partition(vector<int> &arr) {
int n = arr.size();
int pivot = arr[n - 1];
// i acts as boundary between smaller and
// larger element compared to pivot
int i = -1;
for (int j = 0; j < n; j++) {
// If smaller element is found expand the
// boundary and swapping it with boundary element.
if (arr[j] < pivot) {
i++;
swap(arr[i], arr[j]);
}
}
// place the pivot at its correct position
swap(arr[i + 1], arr[n - 1]);
}
int main() {
vector<int> arr = {5, 13, 6, 9, 12, 11, 8};
partition(arr);
for (int i = 0; i < arr.size(); i++)
cout << arr[i] << " ";
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void partition(int arr[], int n) {
int pivot = arr[n - 1];
// i acts as boundary between smaller and
// larger element compared to pivot
int i = -1;
for (int j = 0; j < n; j++) {
// If smaller element is found expand the
// boundary and swapping it with boundary element.
if (arr[j] < pivot) {
i++;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
// place the pivot at its correct position
int temp = arr[i + 1];
arr[i + 1] = arr[n - 1];
arr[n - 1] = temp;
}
int main() {
int arr[] = {5, 13, 6, 9, 12, 11, 8};
int n = sizeof(arr) / sizeof(arr[0]);
partition(arr, n);
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
return 0;
}
import java.util.Arrays;
class GfG {
static void partition(int[] arr) {
int n = arr.length;
int pivot = arr[n - 1];
// i acts as boundary between smaller and
// larger element compared to pivot
int i = -1;
for (int j = 0; j < n; j++) {
// If smaller element is found expand the
// boundary and swapping it with boundary element.
if (arr[j] < pivot) {
i++;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
// place the pivot at its correct position
int temp = arr[i + 1];
arr[i + 1] = arr[n - 1];
arr[n - 1] = temp;
}
public static void main(String[] args) {
int[] arr = {5, 13, 6, 9, 12, 11, 8};
partition(arr);
for (int ele: arr)
System.out.print(ele + " ");
}
}
def partition(arr):
n = len(arr)
pivot = arr[n - 1]
# i acts as boundary between smaller and
# larger element compared to pivot
i = -1
for j in range(n):
# If smaller element is found expand the
# boundary and swapping it with boundary element.
if arr[j] < pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i]
# place the pivot at its correct position
arr[i + 1], arr[n - 1] = arr[n - 1], arr[i + 1]
if __name__ == "__main__":
arr = [5, 13, 6, 9, 12, 11, 8]
partition(arr)
for ele in arr:
print(ele, end = ' ')
using System;
class GfG {
// Function to partition the array according
// to pivot index element
static void partition(int[] arr) {
int n = arr.Length, temp;
int pivot = arr[n - 1];
// i acts as boundary between smaller and
// larger element compared to pivot
int i = -1;
for (int j = 0; j < n; j++) {
// If smaller element is found expand the
// boundary and swapping it with boundary element.
if (arr[j] < pivot) {
i++;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
// place the pivot at its correct position
temp = arr[i+1];
arr[i+1] = arr[n-1];
arr[n-1] = temp;
}
static void Main() {
int[] arr = {5, 13, 6, 9, 12, 11, 8};
partition(arr);
Console.WriteLine(string.Join(" ", arr));
}
}
function partition(arr) {
let n = arr.length;
let pivot = arr[n - 1];
// i acts as boundary between smaller and
// larger element compared to pivot
let i = -1;
for (let j = 0; j < n; j++) {
// If smaller element is found expand the
// boundary and swapping it with boundary element.
if (arr[j] < pivot) {
i++;
[arr[i], arr[j]] = [arr[j], arr[i]];
}
}
// place the pivot at its correct position
[arr[i + 1], arr[n - 1]] = [arr[n - 1], arr[i + 1]];
}
// Driver Code
let arr = [5, 13, 6, 9, 12, 11, 8];
partition(arr);
console.log(arr.join(" "));
Output
5 6 8 9 12 11 13
Some Interesting Facts
- We can easily modify the algorithm to consider the first element (or any other element) as pivot by swapping first and last elements and then using the same code.
- It is easier to understand and implement compared to other partitioning algorithms.
- It generally performs slower than Hoare's partition algorithm, especially in cases of large datasets or when the pivot is poorly chosen, as it may require more swaps.
- Despite its inefficiency, it is still widely used in educational books like Introduction to Algorithms book by Cormen for quick sort, due to its simplicity.