1################################################################################
2# K-th Smallest Element in a Sorted Matrix
3#
4# This function finds the k-th smallest element in an n x n matrix where each row
5# and column is sorted in ascending order. It employs a binary search approach on
6# the possible values of the elements to efficiently find the k-th smallest.
7################################################################################
8
9# Helper function to count elements less than or equal to a given value 'x'.
10# This is the core of the binary search strategy.
11count_less_equal <- function(matrix, x, n) {
12count <- 0
13# Start from the bottom-left corner of the matrix.
14# This is an efficient starting point because if matrix[i, j] <= x,
15# then all elements to its left in the same row (matrix[i, 1...j]) are also <= x.
16# If matrix[i, j] > x, then all elements below it in the same column (matrix[i...n, j]) are also > x.
17row <- n
18col <- 1
19
20while (row >= 1 && col <= n) {
21if (matrix[row, col] <= x) {
22# If the current element is less than or equal to x,
23# it means all elements in this row from col to the end (n) are also <= x.
24# So, we add (n - col + 1) to the count.
25count <- count + (n - col + 1)
26# Move to the next row to check for more elements <= x.
27row <- row - 1
28} else {
29# If the current element is greater than x,
30# it means this element and all elements below it in this column are > x.
31# So, we must move to the left in the same row to find smaller elements.
32col <- col + 1
33}
34}
35return(count)
36}
37
38# Main function to find the k-th smallest element.
39find_kth_smallest <- function(matrix, k) {
40# Get the dimensions of the matrix (assuming it's n x n).
41n <- nrow(matrix)
42
43# Edge case: Empty matrix.
44if (n == 0) {
45stop("Matrix cannot be empty.")
46}
47
48# Edge case: k is out of bounds.
49if (k < 1 || k > n * n) {
50stop(paste("k must be between 1 and", n * n, "inclusive."))
51}
52
53# Define the search space for the k-th smallest element.
54# The smallest possible value is the top-left element.
55# The largest possible value is the bottom-right element.
56low <- matrix[1, 1]
57high <- matrix[n, n]
58ans <- high # Initialize answer to a safe upper bound
59
60# Perform binary search on the range of possible values.
61while (low <= high) {
62# Calculate the middle value in the current search range.
63mid <- floor((low + high) / 2)
64
65# Count how many elements in the matrix are less than or equal to 'mid'.
66count <- count_less_equal(matrix, mid, n)
67
68# If the count of elements <= mid is at least k:
69# This means 'mid' could be our k-th smallest element, or the k-th smallest
70# element is even smaller than 'mid'. We record 'mid' as a potential answer
71# and try to find a smaller value by searching in the lower half.
72if (count >= k) {
73ans <- mid # 'mid' is a candidate for the k-th smallest
74high <- mid - 1 # Search in the lower half
75} else {
76# If the count of elements <= mid is less than k:
77# This means 'mid' is too small. The k-th smallest element must be
78# larger than 'mid'. We search in the upper half.
79low <- mid + 1 # Search in the upper half
80}
81}
82
83# After the binary search, 'ans' will hold the k-th smallest element.
84# The invariant is that 'ans' always stores the smallest value found so far
85# for which count_less_equal(matrix, ans, n) >= k.
86return(ans)
87}
88
89# Example Usage:
90# matrix1 <- matrix(c(1, 5, 9, 10, 11, 13, 15, 16, 19), nrow = 3, byrow = TRUE)
91# k1 <- 8
92# print(paste("The", k1, "-th smallest element is:", find_kth_smallest(matrix1, k1))) # Expected: 16
93
94# matrix2 <- matrix(c(-5), nrow = 1, byrow = TRUE)
95# k2 <- 1
96# print(paste("The", k2, "-th smallest element is:", find_kth_smallest(matrix2, k2))) # Expected: -5
97
98# matrix3 <- matrix(c(1, 2, 3, 4, 5, 6, 7, 8, 9), nrow = 3, byrow = TRUE)
99# k3 <- 5
100# print(paste("The", k3, "-th smallest element is:", find_kth_smallest(matrix3, k3))) # Expected: 5