Algorithm 算法:如何在矩阵中找到一列,填充所有1,时间复杂度O(n)?

Algorithm 算法:如何在矩阵中找到一列,填充所有1,时间复杂度O(n)?,algorithm,matrix,Algorithm,Matrix,我有一个矩阵,看起来像这样: | 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 我可以看到两种可能的解决方案: 取第一列,穿过它,如果看到零,跳到下一

我有一个矩阵,看起来像这样:

| 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

我可以看到两种可能的解决方案:

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

假设任意内容,你就不能避免O(N2)的最坏情况。*你必须访问每一个你想考虑的列中的每一个元素,在最坏的情况下,你必须考虑所有列。


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

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


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

矩阵的输入是什么


如果您为每列获取一个数字,即在您的示例(十进制)14、8、4、31、1中,您可以创建一个
a
,其中
n
二进制数字设置为1(在本例中为31)。如果这个数字等于其中一个列的数字,那么其中一列都是1。

我的解决方案是,我们首先假设所有列都有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+" ");
    }
}
公共类主
{
//给定A:mxn矩阵
公共静态ArrayList solve(整数[][]矩阵)
{
//假设所有列都有1,我们就有列表S
ArrayList S=新的ArrayList();
//S={1,2,…,N}
对于(int i=0;i<矩阵[0]。长度;i++)
{
S.add(i);
}
//第一排:1..M
对于(整数i=0;i
解决方案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+" ");
        }
    }
}
私有类列
{
公共阵列列表数据;
公共整数计数;
公共栏目()
{
数据=新的ArrayList();
计数=0;
}
公共无效添加(int val)
{
添加数据(val);
计数+=val;
}
}
公共班机
{
公共静态void main(字符串[]args)
{
列[]矩阵=
{
新列(),
新列(),
新列()
};
矩阵[0]。添加(1);
矩阵[0]。添加(0);
矩阵[0]。添加(0);
矩阵[1]。添加(1);
矩阵[1]。添加(1);
矩阵[1]。添加(0);
矩阵[2]。增加(1);
矩阵[2]。增加(1);
矩阵[2]。增加(1);
System.out.print(“包含1的列为:”);
for(列:矩阵)
{
if(column.count==column.data.size())
系统输出打印(n+“”);
}
}
}

让我来猜一猜你想做什么。从提到:

  • 数组表示人与人之间的关系
  • 您正在查找一个包含所有1的列
  • 您正试图找到一个
    O(n)
    算法
  • 好吧,你不能在
    O(n)
    中这样做,我可以证明它只是
    O(n^2)

    但是我的猜测是你在做一个经典的,你误解了这个问题

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

    我发现名人身份识别问题,您正在尝试查找类似以下内容:

    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)
    解决方案。

    n
    矩阵中的元素数还是其维度?您需要对算法进行并行化,以使用一个线程或进程处理一列。这就是照相机中矩阵图像处理的方式。@shazin这不会改变算法的复杂性。@shazin:并行化不会改变时间复杂性。除非定义
    n
    ,否则这个问题没有意义-如果是矩阵中的元素数,那么是O(n),如果是方阵的维数,那么是O(n^2)。这假设对任意大小的单词的操作可以在恒定的时间内完成…@OliCharlesworth-是的,没错,确实如此-这可能是一个普遍的兴趣,但作为一个潜在的实现帮助。这并不像人们认为的那样错误,将任意长度单词的基本操作视为O(1)是一个有效且使用的模型(如果可能不太现实,但是,几乎没有一个是,如果你把它们推得太远,它们都是失败的抽象)。但是,你这样做确实应该引起注意。。