如何在O(n)时间

时间:2017-11-10 18:59:51

标签: algorithm time-complexity graph-algorithm directed-graph

我有一个有向图的 n x n 邻接矩阵。我想搜索以查看是否有任何列总结为 n 。问题是我必须在 O(n)时间内完成此操作。有没有办法用 O(n)时间来处理这个问题,或者它是不可能的(不需要代码)?

供参考,以下是我要解决的问题:

问题:

  

在学校的乐队选举期间,每个人对总统都有一些偏好,而且一个人的偏好一直包括他/她自己。 “完美”的总统是每个人的偏好,除了他/她自己不喜欢任何人。我们想要知道的是这样的人是否存在。

     
      
  • 定义一个有向图,其中候选集作为顶点,并且从顶点 a 到顶点 b 的有向边,当且仅当 b 在 a 的首选项集中。
  •   
  • n
  •   
  • 我们想要一个在 O(n)时间
  • 中执行的算法   
  • 我们以 n x n 邻接矩阵的形式给出了上述图形
  •   

我认为如果每个人都投票选出“完美的总统”,那么他/她将拥有 n 传入节点,因此对该列进行求和应该给我们 n 。如果有更好的方法来解决这个问题而不是我正在做的事情,那么任何提示都会受到赞赏,以指导我朝着正确的方向前进。

1 个答案:

答案 0 :(得分:5)

让我重复规则并给出数字以便于参考:

  1. 所有人都喜欢自己
  2. 所有人都喜欢完美的总统(如果有的话)
  3. 完美的总统(如果有的话)不喜欢别人
  4. 让我们定义邻接矩阵,以便当人 i 有一个时,行 i 和列 j 中的值为1对人 j 的偏好。所有其他值均为0.

    上述三条规则可以根据邻接矩阵重新制定如下:

    1. 邻接矩阵的主对角线将全部为1。
    2. 如果完美的总统号码为 i ,则 i 列将包含所有1个
    3. 如果完美的总统号码为 i ,则行 i 将包含全部0,但 i 列除外。< / LI>

      请注意,不能有两个或更多完美的总统,因为他们必须彼此偏好(规则2),这违反了规则3.

      算法:Zig-Zag阶段

      完美的总统(如果存在)可以在线性时间内找到,通过从邻接矩阵的左上角(第0行,第0列)进行锯齿形,根据以下规则:

      • 如果值为1,则向下移动到下一行(同一列)
      • 如果值为0,则向右移动到下一列(同一行)
      • 在保持矩阵边界的同时,不断重复前两步。
      • 如果退出矩阵,则此阶段结束。让我们调用列,我们退出矩阵,列 p

      观察:由于规则1,算法的这一部分永远不会进入主对角线上面的值:该对角线上的1值就像一个每当我们碰到它时,墙壁就会向我们推进。因此,您将始终通过从最后一行向下移动来退出矩阵。在最极端的情况下,它将是在矩阵的右下角(在对角线上)的1向下移动。

      这是一个邻接矩阵的简单示例,其中箭头表示算法如何指示从左上角到底行某处的1的路径:

       1   1   0   1   0
       ↓
       1   1   0   1   0
       ↓
       0 → 1   1   1   0 
           ↓
       0   0 → 0 → 1   0
                   ↓
       0   1   1   1   1
                   ↓
                  =p
      

      请注意,在这个例子中有一个完美的总统,但这当然不是一个要求:算法会给你一个值 p ,无论是否有一个完美的总统。

      声明:完美的总统,如果有的话,必须是号码 p 的人。

      证明

      给定的是上述Zig-zag算法返回的 p

      首先,我们通过矛盾来证明:

      a)完美的总统不能是 i 少于 p 的人。

      所以让我们假设相反:完美的总统是人 i&lt; P

      由于我们在第0列中开始了zig-zag阶段并最终在 p 列中,并且由于我们在此过程中无法跳过列,因此有一段时间我们在列 I 的。由于我们没有停留在该列中,因此它必须意味着列 i 在其中一行中有一个零,这会调用我们向右移动。但是规则2要求如果 i 是一个完美的总统,列 i 应该只有1个值(规则2)。矛盾!

      其次,我们通过矛盾证明:

      b)完美的总统不能是 i 大于 p 的人。

      所以让我们假设相反:完美的总统是人 i&gt; P

      因为我们在第0行开始Zig-zag阶段并到达最后一行(参见观察),并且由于我们在此过程中无法跳过一行,所以有一刻我们在行 i 。由于我们并没有停留在那一行,而是在某个时刻向下移动(参见观察:我们向下移动了矩阵),它必须意味着行 i 它的一列中的一个叫我们向下移动。这1不能是对角线上的1(在 [i,i] ),因为我们没有到达 i 列: i 大于 p ,算法以 p 列结束。所以它必须是行 i 中的另一个,第二个。

      但是规则3要求如果 i 是一个完美的总统,那么行 i 应该只有一个1值,所有其他值都是零。矛盾!

      这两个矛盾的证据让我们没有其他可能的数字,如果有一个完美的总统,而不是数字 p

      算法:验证阶段

      要实际检查人 p 是否确实是一个完美的总统是微不足道的:我们可以检查列 p 是否包含所有1&#39; s和< em> p 只包含0&#39; s, i 列除外。

      时间复杂度

      所有这一切都可以在线性时间内完成:至少 2n-1 在Z字形阶段需要从矩阵读取,而 2n-2 更多最后的验证阶段。因此,这是 O(n)