ℹ️ Select 'Choose Exercise', or randomize 'Next Random Exercise' in selected language.

Choose Exercise:
Timer 00:00
WPM --
Score --
Acc --
Correct chars --

Octave Quickselect for Kth Smallest Element

Octave

Goal -- WPM

Ready
Exercise Algorithm Area
1function kthElement = findKthSmallest(arr, k)
2% Finds the k-th smallest element in an unsorted array using the Quickselect algorithm.
3% Quickselect is related to Quicksort but only recurses on one side of the partition.
4% This makes its average time complexity O(n), but worst-case O(n^2).
5
6n = length(arr);
7
8% --- Input Validation and Edge Cases ---
9if n == 0
10error('Input array cannot be empty.');
11end
12if k < 1 || k > n
13error('k must be between 1 and the length of the array.');
14end
15
16% Quickselect is typically implemented in-place. We'll work on a copy.
17arrCopy = arr;
18
19% Call the recursive helper function.
20kthElement = quickselectHelper(arrCopy, 1, n, k);
21end
22
23function result = quickselectHelper(arr, low, high, k)
24% Recursive helper function for Quickselect.
25% arr: the array (or sub-array) being considered.
26% low: the starting index of the current sub-array.
27% high: the ending index of the current sub-array.
28% k: the rank of the element to find (1-based).
29
30% If the sub-array contains only one element, it's the k-th element.
31if low == high
32result = arr(low);
33return;
34end
35
36% --- Partitioning Step ---
37% Choose a pivot index. A common strategy is to pick the last element.
38% More robust strategies (like median-of-three) can improve performance.
39pivotIndex = high;
40
41% Partition the array around the pivot. Elements smaller than pivot
42% go to the left, larger to the right. The partition function returns
43% the final index of the pivot element.
44pivotFinalIndex = partition(arr, low, high, pivotIndex);
45
46% --- Recursive Step ---
47% The pivot is now at its sorted position (pivotFinalIndex).
48% We need to determine if the k-th smallest element is the pivot itself,
49% or if it lies in the left or right partition.
50
51% If the pivot's final index is exactly k-1 (0-based index for k-th element),
52% then we've found our element.
53if pivotFinalIndex == k - 1
54result = arr(pivotFinalIndex + 1);
55% If the pivot's final index is greater than k-1, the k-th smallest
56% element must be in the left partition.
57elseif pivotFinalIndex > k - 1
58result = quickselectHelper(arr, low, pivotFinalIndex - 1, k);
59% If the pivot's final index is less than k-1, the k-th smallest
60% element must be in the right partition.
61else
62% When recursing on the right side, we are looking for the
63% (k - (pivotFinalIndex - low + 1))-th smallest element within that sub-array.
64% The number of elements to the left of the pivot (inclusive) is (pivotFinalIndex - low + 1).
65result = quickselectHelper(arr, pivotFinalIndex + 1, high, k);
66end
67end
68
69function pIndex = partition(arr, low, high, pivotIndex)
70% Partitions the sub-array arr[low..high] around the pivot element.
71% Elements smaller than the pivot are moved to the left of the pivot,
72% and elements greater are moved to the right.
73% Returns the final index of the pivot element after partitioning.
74
75pivotValue = arr(pivotIndex);
76
77% Move pivot to the end (temporarily) to simplify partitioning logic.
78% This swap is crucial for the logic that follows.
79temp = arr(pivotIndex);
80arr(pivotIndex) = arr(high);
81arr(high) = temp;
82
83storeIndex = low;
84% Iterate through the sub-array from low to high-1 (excluding the pivot).
85for i = low:(high - 1)
86if arr(i) < pivotValue
87% If current element is smaller than pivot, swap it with the element
88% at storeIndex and increment storeIndex.
89temp = arr(i);
90arr(i) = arr(storeIndex);
91arr(storeIndex) = temp;
92storeIndex = storeIndex + 1;
93end
94end
95
96% Move pivot to its final sorted place (just after the last element smaller than it).
97temp = arr(storeIndex);
98arr(storeIndex) = arr(high); % arr(high) is the original pivot value
99arr(high) = temp;
100
101pIndex = storeIndex;
102end
Algorithm description viewbox

Octave Quickselect for Kth Smallest Element

Algorithm description:

This Octave code implements the Quickselect algorithm to efficiently find the k-th smallest element in an unsorted array. It's a selection algorithm that, like Quicksort, uses a partitioning strategy but only recurses on one side of the partition. This makes it highly efficient for finding order statistics.

Algorithm explanation:

The `findKthSmallest` function uses the Quickselect algorithm to find the k-th smallest element in an array. It first performs input validation to ensure `k` is within valid bounds and the array is not empty. The core logic resides in the `quickselectHelper` function, which recursively partitions the array. A `partition` helper function rearranges the sub-array such that elements smaller than a chosen pivot are to its left, and larger elements are to its right. The `quickselectHelper` then determines if the pivot is the k-th element, or if the search should continue in the left or right partition. The average time complexity is O(n), as on average, one partition is discarded in each recursive step. The worst-case time complexity is O(n^2), occurring when the pivot selection consistently leads to highly unbalanced partitions (e.g., always picking the smallest or largest element). The space complexity is O(log n) on average due to recursion depth, and O(n) in the worst case. An invariant is that after `partition` completes, `arr(pivotFinalIndex)` is in its correct sorted position, and all elements before it are smaller, and all elements after it are larger.

Pseudocode:

function findKthSmallest(arr, k):
  n = length(arr)
  if n == 0:
    error 'empty array'
  if k < 1 or k > n:
    error 'invalid k'
  arrCopy = copy of arr
  return quickselectHelper(arrCopy, 1, n, k)

function quickselectHelper(arr, low, high, k):
  if low == high:
    return arr[low]
  pivotIndex = choose pivot (e.g., high)
  pivotFinalIndex = partition(arr, low, high, pivotIndex)
  if pivotFinalIndex == k - 1:
    return arr[pivotFinalIndex + 1]
  else if pivotFinalIndex > k - 1:
    return quickselectHelper(arr, low, pivotFinalIndex - 1, k)
  else:
    return quickselectHelper(arr, pivotFinalIndex + 1, high, k)

function partition(arr, low, high, pivotIndex):
  pivotValue = arr[pivotIndex]
  swap arr[pivotIndex] with arr[high]
  storeIndex = low
  for i from low to high - 1:
    if arr[i] < pivotValue:
      swap arr[i] with arr[storeIndex]
      storeIndex = storeIndex + 1
  swap arr[storeIndex] with arr[high]
  return storeIndex