Partition

Lomuto Partition

// lomuto partition is to return the pivot index to make sure 
// [left, pivot) is smaller than pivot
// (pivot, right] is larger than pivot.
// which means the selected pivot number is the i-th large number in this array.
int lomutoPartition(vector<int>& nums, int left, int right) {
	// select the last element as pivot
	int pivot = nums[right];
	// i start from the left index
	int i = left;
	// j start from the left begining and go to the right - 1 index. (skip right because it is pivot)
	for (int j = left; i < right; ++j) {
		if (nums[j] <= pivot) {
			swap(nums[i], nums[j]);
			++i;
		}
	}
	swap(nums[i], nums[right]);
	return i;
}

Sometimes selecting the last one as pivot point have performance issue. So randomly choose the pivot helps to reduce the time complexity.

int randomPivotLomutoPartition(vector<int>& nums, int left, int right) {
	int pivotIdx = left + std::rand() % (left - right + 1);
	swap(nums[pivotIdx], nums[right]);
	// select the last element as pivot
	int pivot = nums[right];
	// i start from the left index
	int i = left;
	// j start from the left begining and go to the right - 1 index. (skip right because it is pivot)
	for (int j = left; i < right; ++j) {
		if (nums[j] <= pivot) {
			swap(nums[i], nums[j]);
			++i;
		}
	}
	swap(nums[i], nums[right]);
	return i;
}

Three Way Partition

This approach will break stability , a.k.a destroy the original relative order of each element.
But the time complexity is O(N) and space complexity is O(1)

LeetCode question

void threeWayPartition(vector<int>& nums, int left, int right) {
	// randomly switch random number with the last one.
	int randomPivotIdx = left + std::rand() % (right - left + 1);
	swap(nums[randomPivotIdx], nums[right]);
	int pivot = nums[right];
	int mid = left;
	while (left <= right) {
		if (nums[mid] > pivot) {
			swap(nums[mid], nums[left]);
			++mid;
			++left;
		} else if (nums[mid] < pivot) {
			swap(nums[mid], nums[right]);
			--right;
		} else {
			++mid;
		}
	}
}

Another approach would not break the stability but required extra space complexity O(N) and time complexity still keeps in O(n)

void treeWayStablePartition(vector<int>& nums, int left, int right) {
	int m = static_cast<int>(nums.size());
	vector<int> sBuf;
	vector<int> lBuf;
	sBuf.reserve(m);
	lBuf.reserve(m);
	int pivotCounts = 0;
	for (int i : nums) {
		if (i < pivot) {
			sBuf.push_back(i);
		} else if (i > pivot) {
			lBuf.push_back(i);
		} else {
			pivotCounts++;
		}
	}
	int sLen = static_cast<int>(sBuf.size());
	int lLen = static_cast<int>(lBuf.size());
	for (int i = 0; i < sLen; ++i) {
		nums[i] = sBuf[i];
	}
	for (int i = 0; i < pivotCounts; ++i) {
		num[sLen + i] = pivot;
	} 
	for (int i = 0; i < lLen; ++i) {
		nums[sLen + pivotCount + i] = lBuf[i];
	}
	return nums;
}

LeetCode Question

Hoare Partition

// hoare partition is to binairize an arry by the selected pivot value.
// - for all k in [left, p] , nums[k] <= pivot value
// - for all k in (p, right], nums[j] >= pivot value
int loarePartition(vector<int>& nums, int left, int right) {
	int pivot = nums[left + (right - left) / 2];
	int i = left - 1;
	int j = right + 1;
	while (i < j ) {
		do {
			++i;
		} while (nums[i] < pivot);
		do {
			--j;
		} while (nums[j] > pivot);
		if (i >= j) return j;
		swap(nums[i], nums[j]);
	}
	// should never enter here.
	return -1;
}