简体   繁体   中英

find upper left index of subMatrix in C language

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?

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM