Kth Smallest Number in Sorted Matrix

ID: 401; medium

Solution 1 (Java)

public class Solution {

    class Pair {
        int x, y, val;
        public Pair(int x, int y, int val) {
            this.x = x;
            this.y = y;
            this.val = val;
        }
    }
    /**
     * @param matrix: a matrix of integers
     * @param k: An integer
     * @return: the kth smallest number in the matrix
     */
    public int kthSmallest(int[][] matrix, int k) {
        int[] dx = {0, 1};
        int[] dy = {1, 0};
        int n = matrix.length, m = matrix[0].length;
        boolean[][] visited = new boolean[n][m];
        Queue<Pair> minHeap = new PriorityQueue<>(new Comparator<Pair>() {
            public int compare(Pair p1, Pair p2) {
                return p1.val - p2.val;
            }
        });
        minHeap.offer(new Pair(0, 0, matrix[0][0]));

        for (int i = 0; i < k - 1; i++) {
            Pair curr = minHeap.poll();
            for (int j = 0; j < 2; j++) {
                int next_x = curr.x + dx[j];
                int next_y = curr.y + dy[j];
                if (next_x < n && next_y < m && !visited[next_x][next_y]) {
                    Pair next = new Pair(next_x, next_y, matrix[next_x][next_y]);
                    minHeap.offer(next);
                    visited[next_x][next_y] = true;
                }
            }
        }
        return minHeap.peek().val;
    }
}

Notes

  • We use a min heap to keep track of the numbers. This solution is essentially a BFS. Starting from the top left number, which is the minimum number in the matrix, then we add the number on its right and the number below it.

  • We poll the min heap k - 1 times and eventually we end up with the kth smallest number in the heap.

  • It is also important to keep track of which numbers are already visited, just like what is down in graph traversal problems;

  • Time complexity: O(klogn)

Solution 2 (Java)

public class Solution {

    class Result {
        boolean exists;
        int rank;
        public Result(boolean e, int r) {
            exists = e;
            rank = r;
        }
    }
    /**
     * @param matrix: a matrix of integers
     * @param k: An integer
     * @return: the kth smallest number in the matrix
     */
    public int kthSmallest(int[][] matrix, int k) {
        int n = matrix.length, m = matrix[0].length;
        int left = matrix[0][0];
        int right = matrix[n - 1][m - 1];
        while (left <= right) {
            int mid = left + (right - left) / 2;
            Result res = check(mid, matrix);
            if (res.exists && res.rank == k) {
                return mid;
            } else if (res.rank < k) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return left;
    }

    private Result check(int value, int[][] matrix) {
        int n = matrix.length, m = matrix[0].length;
        int i = n - 1, j = 0;
        Result res = new Result(false, 0);
        while (i >= 0 && j < m) {
            if (matrix[i][j] == value)
                res.exists = true;
            if (matrix[i][j] <= value) {
                res.rank += i + 1;
                j += 1;
            } else {
                i -= 1;
            }
        }
        return res;
    }

    
}

Notes

  • Using the sorted property, it is natural to think about binary search.

Last updated