【问题标题】:Algorithm: how to find a column in matrix filled with all 1, time complexity O(n)?算法:如何在矩阵中找到一个全为 1 的列,时间复杂度 O(n)?
【发布时间】:2013-05-27 10:23:07
【问题描述】:

我有一个如下所示的矩阵:

| 1 | 0 | 0 | 1 | 0 |
| 1 | 1 | 0 | 1 | 0 |
| 1 | 0 | 1 | 1 | 0 |
| 1 | 0 | 0 | 1 | 0 |
| 0 | 0 | 0 | 1 | 1 |

我应该找出这个矩阵是否有一列全是 1。在这个矩阵中是第 4 列。据说时间复杂度是 O(n),内存是 O(1)。

这个矩阵表示一组(人)的二元关系。 n是集合的大小,所以矩阵的大小是n * n

我可以看到 2 个可能的解决方案:

  • 取第一列,通过它,如果看到零,跳到下一列,依此类推。但是这个算法最坏的情况是 O(n2);
  • 下一个,如果我将得到所有列的总和,那么我可以在 O(n) 中给出答案。但是在任务条件下并没有说我们已经计算了总和。如果我计算它们,复杂度也将是 O(n2);

还有其他解决方案吗?

【问题讨论】:

  • n是矩阵的元素个数还是维数?
  • 您需要并行化您的算法以使用一个线程或进程处理一列。相机中的矩阵图像处理就是这样完成的。
  • @shazin 这不会改变算法的复杂性。
  • @shazin:并行化不会改变时间复杂度。
  • 这个问题没有意义,除非你定义n - 如果它是矩阵中元素的数量,那么 O(n),如果它是方阵的维数,那么 O( n^2).

标签: algorithm matrix


【解决方案1】:

假设任意内容,您无法避免 O(n2) 的最坏情况。* 您必须访问要考虑的每一列中的每个元素,在最坏的情况下,您必须考虑所有列。


* 这里还假设n是矩阵维度,而不是元素总数。

【讨论】:

    【解决方案2】:

    让我非常疯狂地猜测您要做什么。提示:

    1. 数组表示人与人之间的关系
    2. 您正在查找全为 1 的列
    3. 您正在尝试查找O(n) 算法

    好吧,你不能在 O(n) 中这样做,我可以证明它只是 O(n^2)

    但我的疯狂猜测是你在做一个经典的celebrity identification problem,而你误解了问题。

    名人是其他人都知道但不知道的人 认识任何[其他人]。

    我的名人识别问题,你正在尝试寻找类似的东西:

    Find the number i where
    a[i][x] = 1 for all x            -> every one knows the celebrity
    a[x][i] = 0 for all x != i       -> the celebrity doesn't know anyone else
    

    确实,由于对您要查找的内容有额外的限制,所以有一个O(n) 解决方案。

    【讨论】:

    • 是的,这也是我最初的想法。
    【解决方案3】:

    如果您假设任意内容(如 Oli 的回答)并且您可以将每一行编码为带有二进制标志的无符号整数,那么您可以做到这一点在 O(n) 和 O(1) 中,只需使用最新结果重复执行每一行的逻辑 AND

    最后一组标志将只有相关列也是一个的标志。

    【讨论】:

    • 这假设对任意大小的单词的操作可以在恒定时间内完成......
    • @OliCharlesworth - 是的,确实如此 - 尽管作为潜在的实施帮助,它可能会引起普遍关注。
    • 这并不像人们想象的那么错误,将任意长度单词的基本操作视为 O(1) 是一个有效且使用过的模型(如果可能不是过于现实,但是,几乎没有它们是,如果你把它们推得太远,它们都是失败的抽象)。但是你这样做真的应该注意..它也没有给出列的 index ,但这只会采取 O(log n) 进一步的步骤。
    • 你能提供更多细节吗?因为我不明白如何实现它:(
    【解决方案4】:

    矩阵的输入是什么?

    如果您为每列获取一个数字,即在您的示例中(十进制)14、8、4、31、1,您可以创建一个数字 a,并将 n 二进制数字设置为 1(在本案 31)。如果此数字等于列号之一,则其中一列全为 1。

    【讨论】:

    • 如果矩阵的大小大于您的原生数据类型怎么办?
    • 那么你有一个O(n^2) 的问题。但是,如果他的老师或任何人说有O(n) 解决方案,那么任务描述中就会缺少一些东西。如果 OP 列出了所有信息,则您的解决方案是正确的。
    【解决方案5】:

    我的解决方案是,我们首先假设所有列都有 1,然后我们逐行遍历我们仍然拥有的可能解决方案,并删除不能成为解决方案的列。

    此解决方案是用 Java 编写的:

    解决方案 1:O(n^2) 直截了当

    public class Main
    {
        // Given A: an M x N matrix
        public static ArrayList<Integer> solve (Integer [][] matrix)
        {
            // Assuming all columns have 1s, we have list S
            ArrayList<Integer> S = new ArrayList<Integer>();
    
            // S = { 1, 2, .., N }
            for (int i=0; i < matrix[0].length; i++)
            {
                S.add(i);
            }
    
            // For Row i: 1..M
            for (Integer i = 0; i < matrix.length; i++)
            {
                // For Column j in list S
                for (Integer j : S)
                {
                    if (matrix[i][j] != 1)
                    {
                        S.remove(j);
                    }
                }
            }
    
            return S;
        }
    
        public static void main (String [] args)
        {
            int [][] matrix =
            {
                {1,1,1},
                {0,1,1},
                {0,0,1},
            };
    
            ArrayList<Integer> columns = solve (matrix);
    
            System.out.print(" columns that have 1s are: ");
    
            for (Integer n : columns) System.out.print(n+" ");
        }
    }
    

    解决方案 2:O(n) 使用自定义数据结构

    private class Column
    {
        public ArrayList<Integer> data;
        public int count;
    
        public Column ()
        {
            data = new ArrayList<Integer>();
            count = 0;
        }
    
        public void add (int val)
        {
            data.add(val);
            count += val;
        }
    }
    
    public class Main
    {
    
        public static void main (String [] args)
        {
            Column [] matrix =
            {
                new Column (),
                new Column (),
                new Column ()
            };
    
            matrix[0].add(1);
            matrix[0].add(0);
            matrix[0].add(0);
    
            matrix[1].add(1);
            matrix[1].add(1);
            matrix[1].add(0);
    
            matrix[2].add(1);
            matrix[2].add(1);
            matrix[2].add(1);
    
            System.out.print(" columns that have 1s are: ");
    
            for (Column column : matrix)
            {
                 if (column.count == column.data.size())
                     System.out.print(n+" ");
            }
        }
    }
    

    【讨论】:

    • @OliCharlesworth 检查我添加的第二个解决方案,它是 O(n)
    • 当然,如果你可以做预处理,那么你可以将复杂性成本转移到初始化。
    猜你喜欢
    • 2015-05-25
    • 1970-01-01
    • 2015-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    • 1970-01-01
    相关资源
    最近更新 更多