Reputation: 13
I got to write an algorithm with efficiency of log n - binary search. The program is in c language The question is : We have for example this matrix:
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 1 1 1
0 0 0 0 1 1 1
0 0 0 0 1 1 1
0 0 0 0 1 1 1
we have to find the upper left index of the subMatrix of '1's and return its row and col index. Function header is : void getUpperLeft(int mat[][N], int n, int* row, int* col)
My approach was to go to last row and last cols of the big matrix, find with binary search the first index of '1' . With that i can calculate the size of the small matrix. And then i could do big size mat - sub size mat to find the upper left index.
after that i can extract the row and col index with : pRow = (floor)(index / col) pCol = index % col
My code is unfinished because i think it becomes to complicated.
void getupperLeft(int mat[][N], int n, int* row, int* col)
{
int* startRow = mat[0][N - 1];
int* endRow = mat[N - 1][N - 1];
int* startCol = mat[N - 1][0];
int* endCol = mat[N - 1][N - 1];
int* pCol;
int* pRow;
while (startRow <= endRow)
{
int middleRow = (*startRow + *endRow - N) / 2;
int currentRow = middleRow / N;
int currentCol = middleRow % N;
if (*(mat + N * currentRow + currentCol) == 0 &&
*(mat + ((currentRow + 1) * N) + currentCol) == 1)
{
*pRow = currentRow + 1 * N;
}
else if (*(mat + N * currentRow + currentCol) == 1 &&
*(mat + ((currentRow - 1) * N) + currentCol) == 0)
{
*pRow = currentRow;
}
else
startRow = (currentRow + 1 * N);
}
}
Сan you suggest of a better approach?
Upvotes: 0
Views: 191
Reputation: 63451
You can begin by creating a general binary search function. This simply takes a block of memory and searches for the first non-zero value, examining every stride
elements.
int FindFirstNonZero(const int* mem, int n, int stride)
{
int left = 0, right = (n-1);
while (left < right)
{
int mid = (left + right) / 2;
if (mem[mid * stride] == 0)
{
left = mid + 1;
}
else
{
right = mid;
}
}
return mem[left * stride] != 0 ? left : n;
}
With this, it's quite straight-forward to perform the two binary searches required for your task. First, as you say, look at the last row and find the column. If you find nothing, then the function fails. Otherwise, you perform a search on that column (using a stride of N
) to obtain the row:
int GetUpperLeft(int mat[][N], int* row, int* col)
{
int found = 0;
int c = FindFirstNonZero(mat[N-1], N, 1);
if (c != N)
{
*row = FindFirstNonZero(&mat[0][c], N, N);
*col = c;
found = 1;
}
return found;
}
Called as follows:
int main()
{
int mat[][N] = {
{ 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 1, 1 },
{ 0, 0, 0, 0, 1, 1, 1 },
{ 0, 0, 0, 0, 1, 1, 1 },
{ 0, 0, 0, 0, 1, 1, 1 },
};
int row = -1, col = -1;
int ok = GetUpperLeft(mat, &row, &col);
printf("ok=%d row=%d col=%d\n", ok, row, col);
}
Upvotes: 0