我正在研究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;
}
有人可以帮我理解我的解决方案是否超出了复杂性要求吗?
答案 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)
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