log(n)时间内排序的布尔n * n矩阵中的0的数量

时间:2016-07-02 08:43:49

标签: algorithm search matrix

这是一个谷歌面试问题。

您将获得一个包含N行和N列的矩阵。矩阵中的元素可以是1或0.矩阵的每一行和每列按升序排序。在给定矩阵中找出0-s的数量。

我提出了O(n)解决方案,但根本无法提供O(logn)解决方案。任何指针都非常受欢迎。

编辑:似乎O(logn)似乎不可能,如下所述。

5 个答案:

答案 0 :(得分:2)

首先,这是一个算法计算 O(n)时间内的零:

countZeroes(matrix):
    n = matrix.rowCount
    i = 0
    j = n-1
    count = 0
    while i < n && j >=0:
        if matrix[i][j] == 1 then:
            j--
        else:
            i++
            count += j+1
    return count

每次迭代都会增加 i 或减少 j ,并且两者都只能在循环之前取 0..n-1 之间的值结束,最大迭代次数为 2n ,即 O(n)

这是一个JavaScript代码段,可生成5x5随机矩阵,并使用上述算法对零进行计数:

    function countZeroes(matrix) {
        var n = matrix.length,
            i = 0,
            j = n-1,
            count = 0;
        while (i < n && j >=0) {
            if (matrix[i][j] === 1) {
                j--;
            } else {
                i++;
                count += j+1;
            }
        }
        return count;
    }

    function randomMatrix(n) {
        var matrix = [],
            zeroCounts = [];
        for (var i = 0; i < n; i++) {
            zeroCounts[i] = Math.floor(Math.random() * (n+1));
        }
        zeroCounts.sort((a,b) => b-a); // descending
        for (var i = 0; i < n; i++) {
            matrix[i] = [];
            for (var j = 0; j < n; j++) {
                matrix[i][j] = j < zeroCounts[i] ? 0 : 1;
            }
        }
        return matrix;
    }

    function matrixToString(matrix) {
        var s = '';
        for (var i = 0; i < matrix.length; i++) {
            s += matrix[i].join('') + '\n';
        }
        return s;
    }

    var matrix = randomMatrix(5);
    console.log(matrixToString(matrix));
    console.log('Zeroes: ', countZeroes(matrix));

可以在 O(log n)

中完成

想象一下像这样的矩阵:

0000
0001
0011
0111

您需要访问此矩阵中的每一行才能知道其中有多少个零。想象一下,你只会访问4行中的3行:它可能是任何3行...除非你也访问第4行,否则至少有3个可能的结果为零。

例如,如果您访问过第0行,第1行和第3行,您就会知道:

0000
0001
****
0111

通过对行和列进行排序,您可以扣除:

0000
0001
0**1
0111

但剩余的**可以是000111。找出答案的唯一方法是实际查看该行中的至少一个值。

结论:在 O(n)之内不可能。

答案 1 :(得分:1)

让我们说在算法过程中我们已经知道矩阵具有以下形式:

<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <script>
            myFunction()
            function myFunction() {
              var a="Qt: joe: this is test text1";
              var b="Qt: bella: this is test text2";
              var c="this is test text3";
              var d="Qt: alex: this is test text4";
              removetxt(a);
              removetxt(b);
              removetxt(c);
              removetxt(d);
            }
            function removetxt(x) {
               var x1 = x.replace(/^(Qt:.*:)/g,"");
                alert(x1);
            }

        </script>
    </body>
</html>

我们无法学习任何价值?从任何其他的价值?,所以我们需要看看他们中的每一个。因此,对一般问题的任何解决方案至少需要O( n )时间,以及log( n )或log²( n )中的解决方案)时间是不可能的。

答案 2 :(得分:0)

使用二进制搜索来查找一行中的零数可以帮到这里!

public static int findZerosV2(int[][] NxNMatrix) {
    int numZeros = 0;
    for (int i = 0; i < NxNMatrix.length; i++) {
        int numZerosInRow = binarySearch(NxNMatrix[i]);
        if (numZerosInRow > -1) {
            numZeros += numZerosInRow;
        }
    }
    return numZeros;
}

public static int binarySearch(int[] rowItem) {
    int foundZeros = -1;
    int rowIndex = 0;
    int highIndex = rowItem.length;
    for (int i = 0; i < rowItem.length; i++) {
        //find the middle element 
        int mIndex = (rowIndex + highIndex) / 2;
        if (rowItem[mIndex] == 0) {
            rowIndex = mIndex + 1;
            //keep count using index number of 0
            foundZeros = mIndex;
        } else
            highIndex = mIndex - 1;
    }
    //considering zero based index array
    return foundZeros + 1;
}

答案 3 :(得分:-1)

您可以在每一行上使用二进制搜索来查找0更改为1的位置。 Binarysearch正在处理O(log n)中的排序数组。你会得到改变位置的索引号。你应该为每一行(n次)做,然后时间将是O(n * log n)

答案 4 :(得分:-1)

二进制搜索&#34;中间&#34;在反对角线上指向,然后你就会知道左上角的子矩阵满0,右下角则满1.左下和右下子矩阵的递归搜索? / p>