简体   繁体   English

在 C 语言中查找子矩阵的左上索引

[英]find upper left index of subMatrix in C language

I got to write an algorithm with efficiency of log n - binary search.我必须编写一个具有 log n 效率的算法 - 二进制搜索。 The program is in c language The question is: We have for example this matrix:该程序采用 c 语言问题是:例如,我们有这个矩阵:

                  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.我们必须找到 '1' 的子矩阵的左上角索引并返回它的行和列索引。 Function header is: void getUpperLeft(int mat[][N], int n, int* row, int* col) Function header 是: 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'.我的方法是 go 到大矩阵的最后一行和最后一个列,通过二进制搜索找到“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之后我可以提取行和列索引: 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? Сan你建议一个更好的方法吗?

You can begin by creating a general binary search function.您可以从创建通用二进制搜索 function 开始。 This simply takes a block of memory and searches for the first non-zero value, examining every stride elements.这只需要一块 memory 并搜索第一个非零值,检查每个stride元素。

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.如果什么也没找到,则 function 失败。 Otherwise, you perform a search on that column (using a stride of N ) to obtain the row:否则,您对该列执行搜索(使用N的步幅)以获取该行:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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