思路
- 小行星碰撞的话,应该把目前扫描到的行星从后往前,和此前扫描的行星依次对比,因此应该想到用栈解决问题
- 具体的碰撞判断条件为,栈顶的小行星向右(+),此时扫描到的行星向左(-),这样才会碰撞,然后对于碰撞的结果也要分三种情况:
- 现在的行星大:栈顶弹出,继续判断
- 一样大:栈顶弹出,结束判断
- 现在的行星小:结束判断
这个循环的终止条件为栈空或者是无法碰撞
- 在碰撞循环结束后要根据不同的条件决定是否要把当前行星加入到栈中
时空复杂度
- 时间复杂度:每个元素最多入栈、出栈一次,所以是O(n)
- 空间复杂度:O(n)
注意代码中如何把栈转变为数组~
stars.stream().mapToInt(i -> i).toArray()
AC代码
class Solution {
public int[] asteroidCollision(int[] asteroids) {
Stack<Integer> stars = new Stack<>();
for (int as : asteroids) {
boolean isPush = true;
while (!stars.empty() && stars.peek() > 0 && as < 0) {
if (stars.peek() > -as) {
isPush = false;
break;
} else if (stars.peek() == -as) {
isPush = false;
stars.pop();
break;
} else
stars.pop();
}
if (isPush)
stars.push(as);
}
return stars.stream().mapToInt(i -> i).toArray();
}
}
Go代码
type Stack struct {
stack []int
}
func (this *Stack) push(num int) {
this.stack = append(this.stack, num)
}
func (this *Stack) pop() int {
length := len(this.stack)
if length == 0 {
return 0
}
num := this.stack[length-1]
this.stack = this.stack[0 : length-1]
return num
}
func (this *Stack) top() int {
if len(this.stack) == 0 {
return 0
}
return this.stack[len(this.stack)-1]
}
func (this *Stack) empty() bool {
return len(this.stack) == 0
}
func asteroidCollision(asteroids []int) []int {
stack := &Stack{}
for _, asteroid := range asteroids {
if !judgeCollision(stack, asteroid) {
stack.push(asteroid)
} else {
collision(stack, asteroid)
}
}
return stack.stack
}
// 判断是否会撞上
func judgeCollision(stack *Stack, asteroid int) bool {
if stack.empty() || asteroid > 0 {
return false
}
if asteroid < 0 && stack.top() < 0 {
return false
}
return true
}
func collision(stack *Stack, asteroid int) {
for !stack.empty() && stack.top() > 0 {
top := stack.top()
result := top + asteroid
if result > 0 {
return
} else if result == 0 {
stack.pop()
return
} else {
stack.pop()
}
}
stack.push(asteroid)
}