簡體   English   中英

在 C 語言中查找子矩陣的左上索引

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

我必須編寫一個具有 log n 效率的算法 - 二進制搜索。 該程序采用 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

我們必須找到 '1' 的子矩陣的左上角索引並返回它的行和列索引。 Function header 是: void getUpperLeft(int mat[][N], int n, int* row, int* col)

我的方法是 go 到大矩陣的最后一行和最后一個列,通過二進制搜索找到“1”的第一個索引。 有了它,我可以計算小矩陣的大小。 然后我可以做大尺寸墊子 - 子尺寸墊子來找到左上角的索引。

之后我可以提取行和列索引: pRow = (floor)(index / col) pCol = index % col

我的代碼未完成,因為我認為它變得復雜。

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你建議一個更好的方法嗎?

您可以從創建通用二進制搜索 function 開始。 這只需要一塊 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;
}

有了這個,執行任務所需的兩個二進制搜索就非常簡單了。 首先,正如您所說,查看最后一行並找到該列。 如果什么也沒找到,則 function 失敗。 否則,您對該列執行搜索(使用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;
}

調用如下:

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