🧠
Prefix XOR Matrix + Min-Heap of Size k
💡 This approach optimizes space and time by avoiding sorting all XOR values, instead maintaining a min-heap of size k to track the kth largest value dynamically.
Intuition
Use prefix XOR to compute all XOR coordinate values, but instead of sorting all, keep a min-heap of size k to store the top k values seen so far.
Algorithm
- Create prefix XOR matrix as before.
- Initialize a min-heap to store up to k XOR values.
- For each prefix XOR value, if heap size < k, push it; else if current value > heap top, pop top and push current.
- After processing all values, the heap top is the kth largest XOR coordinate value.
💡 Maintaining a min-heap of size k ensures efficient top-k tracking without sorting all values.
import heapq
def kthLargestValue(matrix, k):
m, n = len(matrix), len(matrix[0])
prefix = [[0] * (n + 1) for _ in range(m + 1)]
min_heap = []
for i in range(1, m + 1):
for j in range(1, n + 1):
prefix[i][j] = prefix[i - 1][j] ^ prefix[i][j - 1] ^ prefix[i - 1][j - 1] ^ matrix[i - 1][j - 1]
val = prefix[i][j]
if len(min_heap) < k:
heapq.heappush(min_heap, val)
elif val > min_heap[0]:
heapq.heapreplace(min_heap, val)
return min_heap[0]
# Example usage
if __name__ == '__main__':
matrix = [[5,2],[1,6]]
k = 3
print(kthLargestValue(matrix, k)) # Output: 4
Line Notes
import heapqImport heapq module for min-heap operations
min_heap = []Initialize empty min-heap to track top k values
if len(min_heap) < k:If heap not full, push current value
heapq.heappush(min_heap, val)Add value to min-heap
elif val > min_heap[0]:If current value larger than smallest in heap, replace
heapq.heapreplace(min_heap, val)Pop smallest and push current value to maintain size k
return min_heap[0]Heap root is kth largest value after processing all
import java.util.*;
public class Solution {
public int kthLargestValue(int[][] matrix, int k) {
int m = matrix.length, n = matrix[0].length;
int[][] prefix = new int[m + 1][n + 1];
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
prefix[i][j] = prefix[i - 1][j] ^ prefix[i][j - 1] ^ prefix[i - 1][j - 1] ^ matrix[i - 1][j - 1];
int val = prefix[i][j];
if (minHeap.size() < k) {
minHeap.offer(val);
} else if (val > minHeap.peek()) {
minHeap.poll();
minHeap.offer(val);
}
}
}
return minHeap.peek();
}
public static void main(String[] args) {
Solution sol = new Solution();
int[][] matrix = {{5,2},{1,6}};
int k = 3;
System.out.println(sol.kthLargestValue(matrix, k)); // Output: 4
}
}
Line Notes
PriorityQueue<Integer> minHeap = new PriorityQueue<>();Min-heap to track top k XOR values
if (minHeap.size() < k) {Add values until heap size reaches k
minHeap.offer(val);Add current larger value
else if (val > minHeap.peek()) {Replace smallest if current value is larger
minHeap.poll();Remove smallest value from heap
return minHeap.peek();Heap root is kth largest XOR value
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int kthLargestValue(vector<vector<int>>& matrix, int k) {
int m = matrix.size(), n = matrix[0].size();
vector<vector<int>> prefix(m + 1, vector<int>(n + 1, 0));
priority_queue<int, vector<int>, greater<int>> minHeap;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
prefix[i][j] = prefix[i - 1][j] ^ prefix[i][j - 1] ^ prefix[i - 1][j - 1] ^ matrix[i - 1][j - 1];
int val = prefix[i][j];
if ((int)minHeap.size() < k) {
minHeap.push(val);
} else if (val > minHeap.top()) {
minHeap.pop();
minHeap.push(val);
}
}
}
return minHeap.top();
}
int main() {
vector<vector<int>> matrix = {{5,2},{1,6}};
int k = 3;
cout << kthLargestValue(matrix, k) << endl; // Output: 4
return 0;
}
Line Notes
priority_queue<int, vector<int>, greater<int>> minHeap;Min-heap to maintain top k XOR values
if ((int)minHeap.size() < k) {Push values until heap size reaches k
minHeap.push(val);Add current larger value
else if (val > minHeap.top()) {Replace smallest if current value is larger
minHeap.pop();Remove smallest value
return minHeap.top();Heap root is kth largest XOR value
class MinHeap {
constructor() {
this.heap = [];
}
size() {
return this.heap.length;
}
peek() {
return this.heap[0];
}
push(val) {
this.heap.push(val);
this.bubbleUp();
}
pop() {
const top = this.heap[0];
const end = this.heap.pop();
if (this.heap.length > 0) {
this.heap[0] = end;
this.bubbleDown();
}
return top;
}
bubbleUp() {
let idx = this.heap.length - 1;
const element = this.heap[idx];
while (idx > 0) {
let parentIdx = Math.floor((idx - 1) / 2);
let parent = this.heap[parentIdx];
if (element >= parent) break;
this.heap[parentIdx] = element;
this.heap[idx] = parent;
idx = parentIdx;
}
}
bubbleDown() {
let idx = 0;
const length = this.heap.length;
const element = this.heap[0];
while (true) {
let leftIdx = 2 * idx + 1;
let rightIdx = 2 * idx + 2;
let swap = null;
if (leftIdx < length) {
if (this.heap[leftIdx] < element) swap = leftIdx;
}
if (rightIdx < length) {
if ((swap === null && this.heap[rightIdx] < element) || (swap !== null && this.heap[rightIdx] < this.heap[leftIdx])) {
swap = rightIdx;
}
}
if (swap === null) break;
this.heap[idx] = this.heap[swap];
this.heap[swap] = element;
idx = swap;
}
}
}
function kthLargestValue(matrix, k) {
const m = matrix.length, n = matrix[0].length;
const prefix = Array.from({length: m + 1}, () => Array(n + 1).fill(0));
const minHeap = new MinHeap();
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
prefix[i][j] = prefix[i - 1][j] ^ prefix[i][j - 1] ^ prefix[i - 1][j - 1] ^ matrix[i - 1][j - 1];
const val = prefix[i][j];
if (minHeap.size() < k) {
minHeap.push(val);
} else if (val > minHeap.peek()) {
minHeap.pop();
minHeap.push(val);
}
}
}
return minHeap.peek();
}
// Example usage
const matrix = [[5,2],[1,6]];
const k = 3;
console.log(kthLargestValue(matrix, k)); // Output: 4
Line Notes
class MinHeap {Custom min-heap implementation for top k tracking
minHeap.push(val);Add value to min-heap when size < k
minHeap.peek()Get smallest value in heap to compare
minHeap.pop();Remove smallest value when current is larger
prefix[i][j] = prefix[i - 1][j] ^ prefix[i][j - 1] ^ prefix[i - 1][j - 1] ^ matrix[i - 1][j - 1];Compute prefix XOR with inclusion-exclusion
return minHeap.peek();Return kth largest XOR value after processing all
TimeO(m * n * log k) due to heap operations for each coordinate
SpaceO(m * n) for prefix matrix plus O(k) for heap
Prefix XOR is O(m*n), each heap operation is O(log k), total O(m*n log k).
💡 For k=10 and a 1000x1000 matrix, this is about 1,000,000 * log 10 ≈ 2,000,000 operations, efficient for interviews.
Interview Verdict: Accepted
This is the optimal approach balancing time and space, preferred in interviews for large inputs.