计算许多鱼的时间和空间复杂性还活着吗?

时间:2018-03-14 21:53:37

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

我正在研究Codility问题:

  

您将获得两个非空的零索引数组A和B.   N个整数。数组A和B代表河流中的N鱼类,   沿着河流顺序下游。

     

鱼的编号从0到N-1。如果P和Q是两条鱼而P <1。   Q,那么鱼P最初是鱼Q的上游。最初,每条鱼   有一个独特的位置。

     

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

     

0代表上游流动的鱼,1代表鱼流动   下游。如果两条鱼向相反方向移动而没有   在他们之间的其他(生活)鱼,他们最终将满足每一个   其他。然后只有一条鱼可以活着 - 较大的鱼吃了   较小的一个。更准确地说,我们说两条鱼P和Q相遇   其他当P < Q,B [P] = 1且B [Q] = 0,没有活鱼   它们之间。他们见面后:

     

如果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;
}

有人可以帮我理解我的解决方案是否超出了复杂性要求吗?

5 个答案:

答案 0 :(得分:2)

您的想法很好。 我试图使其更易于理解。

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;
    }
}

答案 1 :(得分:1)

使用奇怪的数据结构和缺少变量名称来跟踪此代码很难,但我认为我有必要的理解......

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

时间复杂度: 鉴于你的奇怪逻辑,这更难以遵循。成对的remFish减少和while -- break的滥用使我困惑了几分钟。但是,更简单的分析是......

while -- break将循环转换为简单的if语句,因为总是在第一次迭代时中断循环。因此,您唯一真正的迭代是for循环,以鱼的数量为界。因此,这也是 O(n)

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

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

答案 2 :(得分:0)

N鱼获得了一系列O(1)次检查。那是O(n)

游泳到下游的O(n)鱼被添加到myQ,其中O(1)的每个O(n)期限也会增加O(1)

内循环的每次迭代都会在O(n)时间内杀死一条鱼。最多O(n)条鱼死亡,因此也是O(n)

全部添加,总数为.show-grid [class*="span"] {

答案 3 :(得分:0)

我得到了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;

答案 4 :(得分:0)

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

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