【问题标题】:Time and Space complexity for calculating many fish are alive? [closed]计算许多鱼的时间和空间复杂度是活的? [关闭]
【发布时间】:2018-08-23 14:25:20
【问题描述】:

我正在处理一个 Codility 问题:

给定两个非空的零索引数组 A 和 B,包括 N 个整数。数组 A 和 B 代表河流中的 N 条贪婪的鱼, 顺着河流顺流而下。

鱼从 0 到 N - 1 编号。如果 P 和 Q 是两条鱼并且 P

鱼数P用A[P]和B[P]表示。数组 A 包含 鱼的大小。它的所有元素都是独一无二的。数组 B 包含 鱼的方向。它仅包含 0 和/或 1,其中:

0代表一条鱼在上游,1代表一条鱼在上游 下游。如果两条鱼朝相反的方向移动并且没有 他们之间的其他(活)鱼,他们最终会相遇 其他。那么只有一条鱼可以活着——大鱼吃掉了 较小的一个。更准确地说,我们说两条鱼 P 和 Q 相遇 其他当 P

如果 A[P] > A[Q] 那么 P 吃掉 Q,P 仍然会顺流而下, 如果 A[Q] > A[P] 则 Q 吃掉 P,Q 仍将向上游流动。我们 假设所有的鱼都以相同的速度流动。也就是鱼 朝着同一个方向前进,永远不会相遇。目标是计算 能存活的鱼的数量。

**Complexity:**

预期的最坏情况时间复杂度为 O(N); 预期的最坏情况空间复杂度为 O(N),超出输入存储(不计算输入参数所需的存储)。

这是我的解决方案:(100% 正确的结果)

public int solution(int[] a, int[] b) {
  int remFish = a.length; 
  int i = 0; 
  for (i = 0; i < b.length; i++) {
    if(b[i] != 0){
      /*remFish++; }else { */ break; 
    }
  } 
  Stack<Integer> myQ = new Stack<Integer>(); 
  for (int j = i; j < b.length; j++) { 
    if(b[j] == 1)
    {
      myQ.add(j); 
    } 
    while(b[j] == 0 && !myQ.isEmpty()) {
      if(a[j] > a[myQ.peek()]){ 
        myQ.pop(); remFish--; 
      }else{ 
        remFish--; 
      break; 
      }
    } 
  } 
  return remFish;
}

有人可以帮助我了解我的解决方案是否通过了复杂性要求吗?

【问题讨论】:

    标签: java algorithm performance time-complexity space-complexity


    【解决方案1】:

    这里是 python3 尝试,时间复杂度为 O(N)

    def fish_eater(fish_size, direction):
        stack = []
        fish_alive = len(fish_size)
        if not len(fish_size):
            return 0
        for i in range(len(fish_size)):
            if direction[i] == 1:
                stack.append(fish_size[i])
            else:
                while len(stack):
                    if stack[-1] > fish_size[i]:
                        fish_alive -= 1
                        break
                    if stack[-1] < fish_size[i]:
                        fish_alive -= 1
                        stack.pop()
        return fish_alive
    
    

    关于时间复杂度和大 O 符号的有用资源 understanding-time-complexity-with-python

    【讨论】:

    • 不尝试回答问题“有人可以帮助我了解我的解决方案是否通过复杂性要求吗?”。
    【解决方案2】:

    我用这个代码得到了 100/100。我见过其他更简洁的解决方案。但这一篇可读性很强。

    ArrayDeque<Integer> downstreams = new ArrayDeque<>();
        int alive = 0;
        for (int i = 0; i < A.length; i++) {
            int currFish = A[i] * (B[i] == 1 ? -1 : 1);
            if (currFish < 0) {
                downstreams.push(currFish);
                alive++;
            } else {
                Iterator it = downstreams.iterator();
                boolean eaten = false;
                while (it.hasNext()) {
                    int down = (int) it.next();
                    if (Math.abs(currFish) > Math.abs(down)) {
                        it.remove();
                        alive--;
                        eaten = false;
                    } else {
                        eaten = true;
                        break;
                    }
                }
                if (!eaten) {
                    alive++;
                }
            }
        }
        return alive;
    

    【讨论】:

      【解决方案3】:

      你的想法很好。 我试图让它更容易理解。

      import java.util.*;
      
      class Solution {
          public int solution(int[] A, int[] B) {
      
              int numFishes = A.length;
      
              // no fishes
              if(numFishes == 0)
                  return 0;
      
              // Deque stores the fishes swimming downstreams (B[i]==1) 
              Deque<Integer> downstreams = new ArrayDeque<Integer>();
      
              for(int i = 0; i < A.length; i++){
      
                  //Fish is going downstreams
                  if(B[i] == 1){
                      // push the fish into the Deque
                      downstreams.push(A[i]); 
                  }//Fish is going upstreams
                  else{
                      while( !downstreams.isEmpty() ){ 
                          // Downstream-fish is bigger 
                          if( downstreams.peek() > A[i] ){
                              //Upstream-fish gets eaten
                              numFishes--;
                              break;    
                          }// Downstream-fish is smaller
                          else if(downstreams.peek() < A[i]){
                              //Downstream-fish gets eaten
                              numFishes--;
                              downstreams.pop();
                          }
                      }
                  }  
              }    
      
              return numFishes;
          }
      }
      

      【讨论】:

        【解决方案4】:

        Nfish 得到一系列O(1) 检查。那是O(n)

        O(n) 向下游游泳的鱼被添加到 myQ,这也是 O(1) 每个 O(n) 术语。

        内循环的每次迭代都会在O(1) 时间内杀死一条鱼。至多O(n)鱼死了所以也是O(n)

        全部加起来,总数为O(n)

        【讨论】:

          【解决方案5】:

          由于奇怪的数据结构和缺少变量名,很难遵循这段代码,但我认为我有必要的理解......

          空间复杂度: 您拥有的唯一尺寸空间是myQ,它以鱼的总量为界。因此,这是 O(n)

          时间复杂度: 鉴于您奇怪的逻辑,这很难理解。 remFish 的成对递减和while -- break 的滥用让我困惑了几分钟。然而,更简单的分析是......

          while -- break 将该循环变成一个简单的if 语句,因为您总是在第一次迭代时中断循环。因此,您唯一真正的迭代是for 循环,受鱼数量的限制。因此,这也是 O(n)

          在其他属性中,请注意您在每次迭代中递减 numFish,并且它永远不会下降到 0。


          为什么你在 a.length 上测量一次迭代,在 b.length 上测量另一个迭代?那些必须是相同的,鱼的起始数量。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-04-09
            • 2020-05-03
            • 1970-01-01
            • 2021-01-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多