this is a google interview question :
Given a N*N Matrix. All rows are sorted, and all columns are sorted. Find the Kth Largest element of the matrix.
doing
My code below is an O(k) algorithm. It does not work on a certain edge case (probably one in each direction: x and y). I listed the edge case so someone can fix it. I'm not going to fix it because it's bed time for me.
Summary of algorithm: you only need to keep track of two candidate #s that might be the smallest, one while proceeding in the x-direction and one while proceeding in the y-direction. Think about it and it might make sense to you.
enum Direction {
X,
Y
};
struct Index
{
Index(int unsigned x, int unsigned y)
: x(x),
y(y)
{}
void operator = (Index const & rhs)
{
x = rhs.x;
y = rhs.y;
}
int unsigned x;
int unsigned y;
};
int unsigned solve(int unsigned i_k, int unsigned ** i_data, int unsigned i_n)
{
if (1 == i_k) {
return i_data[0][0];
}
Direction dir = X;
Index smaller(0,0);
Index larger(0,0);
if (i_data[1][0] < i_data[0][1]) {
dir = X;
smaller = Index(1,0);
larger = Index(0,1); }
else {
dir = Y;
smaller = Index(0,1);
larger = Index(1,0);
}
for (int unsigned i = 0; i < (i_k - 2); ++i) {
int unsigned const x = smaller.x;
int unsigned const y = smaller.y;
if (X == dir) {
if ((x + 1) == i_n) {
// End of row
smaller = larger;
larger.x += 1;
dir = Y; }
else if (i_data[x + 1][y] < i_data[larger.x][larger.y]) {
smaller.x += 1; }
else {
smaller = larger;
larger = Index(x + 1, y);
dir = Y;
} }
else {
if ((y + 1) == i_n) {
// End of col
smaller = larger;
larger.y += 1;
dir = X; }
else if (i_data[x][y + 1] < i_data[larger.x][larger.y]) {
smaller.y += 1; }
else {
smaller = larger;
larger = Index(x, y + 1);
dir = X;
}
}
}
return i_data[smaller.x][smaller.y];
}
doesn't work on the following edge case (where we hit the end of a row). I'm going to bed, feel free to fix this case:
size = 4;
data = createMatrix(size);
data[0][0] = 1; data[1][0] = 6; data[2][0] = 10; data[3][0] = 11;
data[0][1] = 3; data[1][1] = 7; data[2][1] = 12; data[3][1] = 14;
data[0][2] = 4; data[1][2] = 8; data[2][2] = 13; data[3][2] = 15;
data[0][3] = 5; data[1][3] = 9; data[2][3] = 19; data[3][3] = 20;
answer = solve(14, data, size);
assertAnswer(answer, 15, ++testNum);
deleteMatrix(data, size);
Yes, there is an O(K) algorithm due to Frederickson and Johnson.
Greg N. Frederickson and Donald B. Johnson. Generalized Selection and Ranking: Sorted Matrices. SIAM J. Comput. 13, pp. 14-30. http://epubs.siam.org/sicomp/resource/1/smjcat/v13/i1/p14_s1?isAuthorized=no