给定一个整数数组 asteroids,表示在同一行的行星。对于数组中的每一个元素,其绝对值表示行星的大小,正负表示行星的移动方向(正表示向右移动,负表示向左移动)。每一颗行星以相同的速度移动。找出碰撞后剩下的所有行星。碰撞规则:两个行星相互碰撞,较小的行星会爆炸。如果两颗行星大小相同,则两颗行星都会爆炸。两颗移动方向相同的行星,永远不会发生碰撞。
示例 1:输入: asteroids = [5, 10, -5]输出: [5, 10]
解释: 10 和 -5 碰撞后只剩下 10。 5 和 10 永远不会发生碰撞。
示例 2:输入: asteroids = [8, -8]输出: []
解释: 8 和 -8 碰撞后,两者都发生爆炸。
示例 3:输入: asteroids = [10, 2, -5]输出: [10]
解释: 2 和 -5 发生碰撞后剩下 -5。10 和 -5 发生碰撞后剩下 10。
示例 4:输入: asteroids = [-2, -1, 1, 2]输出: [-2, -1, 1, 2]
解释: -2 和 -1 向左移动,而 1 和 2 向右移动。由于移动方向相同的行星不会发生碰撞,所以最终没有行星发生碰撞。
说明:数组 asteroids 的长度不超过 10000。每一颗行星的大小都是非零整数,范围是 [-1000, 1000] 。
在读了一遍题目之后,我们应该首先我们确定下该算法所需要的数据结构:
思考ing
对 你想到了我们应该用栈Stack。
为什么用栈呢?
嗯首先我们的输入是一个数组,输出是一个数组,挨个的放数,然后再后面存进去的时候要和之前已经存进去的进行比较,直到合适的位置,也就是要后进先出。即栈。
我用的是Java自带的类库,你也可以自己用数组模仿实现,效果类似。
那么接下来,在我们数据结构清晰的情况下,进行算法设计就不是很难了,滴滴滴开车啦
我们首先对题目的情况再进行细致的分析,
1、当左边的全是负数,也就是向左飞,右边全是正数,也就是向右飞,就不会相撞,这时候我们就找到了第一个临界点,也就是左边全是负数时,突然右边来了一个正数,那么是不会发生碰撞的。
2、请问啥时会发生碰撞?答案是正数在左边时也就是正数先进栈,突然来了一个负数,这时候就会发生碰撞。碰撞会产生三种情况
2.1、当栈顶正数大于负数绝对值时,负数无作用,数组指针指向下一个,正数返回栈内
2.2、当正负数绝对值相同时,将栈顶元素推出。
2.3、当正数小于负数绝对值,负数存活,栈顶指针下移,和下一个栈顶指针比较,直到栈顶为负(1)或者是栈顶正数大于等于负数绝对值时(2.1,2.2)
我们再将栈转为数组进行输出,即得到结果。
综上所述算法解决
代码如下所示:
class Solution {
public int[] asteroidCollision(int[] a) {
Stack<Integer> stack=new Stack<>();
int j=1;
for(int i=0;i<a.length;i++){
if(stack.empty()){
stack.push(a[i]); // 初始化栈
}
else if((stack.peek()<0&&a[i]<0)||(stack.peek()>0&&a[i]>0)||(stack.peek()<0&&a[i]>0))
{
stack.push(a[i]);//当栈顶位置元素和数组下个正负一致,以及1情况
j++;
}
else{
if(stack.peek()>0&&a[i]<0){
if(-a[i]<stack.peek())//2.1
;
else if(-a[i]==stack.peek()){
int rubish=stack.pop();//2.2
}
else{
while(!stack.empty()&&stack.peek()>0&&stack.peek()<(-a[i])){
stack.pop();//2.3,找到合适的位置
}
if(!stack.empty()&&stack.peek()==(-a[i])){
stack.pop();//插入数组元素
}
else if(stack.empty()||stack.peek()<0){
stack.push(a[i]);//插入数组元素
}
else
;
}
}
}
}
int[] temp= new int[stack.size()];
for(int i=0;i<temp.length;i++){//将栈转换为数组
if(stack.get(i)!=0){
temp[i]=stack.get(i);
}
}
return temp;
}
}
最后宣传下我个人的微信公众号,微信搜索:可及的小屋,有志向整副业,娱乐的程序员们,欢迎您的到来。谢谢。
100G程序员资料,自取哦!!