2.1 Find the kth smallest number in sorted matrix
Given a matrix of size n x m. For each row the elements are sorted in ascending order, and for each column the elements are also sorted in ascending order. Find the kth smallest number in it.
Assumption: the matrix is not null, n, m > 0. 0 < k <= n*m
Input: int[][] matrix, int k
Output: int the smallest number
Solution:
Initial state: [0][0]
Expand[i][j] → generate [i][j+1]
generate [i+1][j]
3. Terminate condition: after expanding k times
4. Dedup: use boolean[][] to mark generated numbers
TC: k iterations to run k
for each iteration:
pop one element out of pq log2k (pq.size <= 2k)
generate right log2k
bottom log2k
Total: k * 3log2k = O(klogk)
class Cell {
int row;
int col;
int value;
Cell(int row, int col, int value) {
this.row = row;
this.col = col;
this.value = value;
}
}
public int kthSmallest(int[][] matrix, int k) {
int rows = matrix.length;
int cols = matri[0].length;
PriorityQueue<Cell> minHeap = new PriorityQueue<Cell>(k, new Comparator<Cell>(){
@Override
public int compare(Cell c1, Cell c2) {
if (c1.value == c2.value) { return 0; }
return c1.value < c2.value ? -1 : 1;
}
});
boolean[][] visited = new boolean[rows][cols];
minHeap.offer(new Cell(0, 0, matrix[0][0]);
visited[0][0] = true;
for (int i = 0; i < k - 1; i++) {
Cell cur = minHeap.poll();
if (cur.row + 1 < rows && !visited[cur.row + 1][cur.col]) {
minHeap.offer(new Cell(cur.row + 1, cur.col, matrix[cur.row + 1][cur.col]));
visited[cur.row + 1][cur.col] = true;
}
if (cur.col + 1< cols && !visited[cur.row][cur.col + 1]) {
minHeap.offer(new Cell(cur.row, cur.col + 1, matrix[cur.row][cur.col + 1]));
visited[cur.row][cur.col + 1] = true;
}
}
return minHeap.peek().value;
}Similar solution to question: Kth Smallest Sum In Two Sorted Arrays
Given two sorted arrays A and B, of sizes m and n respectively. Define sum = a + b, where a is one element from A and b is one element from B. Find the Kth smallest sum out of all possible sums. Assumption: A and B are not null and length > 0. k > 0 and K <= m * n.
class Cell {
int i;
int j;
int sum;
public Cell(int i, int j, int sum) {
this.i = i;
this.j = j;
this.sum = sum;
}
}
public int kthSum(int[] A, int[] B, int k) {
PriorityQueue<Cell> pq = new PriorityQueue<>(1, new Comparator<Cell>(){
@Override
public int compare(Cell a, Cell b) {
return a.sum - b.sum;
}
});
boolean[][] visited = new boolean[A.length][B.length];
pq.offer(new Cell(0, 0, A[0] + B[0]));
visited[0][0] = true;
for (int i = 1; i < k; i++) {
Cell cur = pq.poll();
if (cur.i + 1 < A.length && !visited[cur.i + 1][cur.j]) {
pq.offer(new Cell(cur.i + 1, cur.j, A[cur.i + 1] + B[cur.j]));
visited[cur.i + 1][cur.j] = true;
}
if (cur.j + 1 < B.length && !visited[cur.i][cur.j + 1]) {
pq.offer(new Cell(cur.i, cur.j + 1, A[cur.i] + B[cur.j + 1]));
visited[cur.i][cur.j + 1] = true;
}
}
return pq.peek().sum;
}Last updated
Was this helpful?