返回
行星碰撞 Java 题解:领悟背后的物理直觉
后端
2023-12-01 05:47:48
引言
在浩瀚的太空,行星的碰撞是常见的现象。在计算机科学领域,行星碰撞问题在 LeetCode 等编程平台上也广受关注。这个问题看似复杂,但如果你掌握了背后的物理直觉,它将变得清晰明了。
物理直觉
行星碰撞的物理原理非常简单:
- 质量越大,动能越大: 一个行星的动能与它的质量成正比。
- 动能守恒: 碰撞前后,系统的总动能守恒。
算法思路
基于上述物理直觉,我们可以设计一个贪心算法来解决这个问题:
- 初始化一个栈: 栈中存储的是尚未处理的行星。
- 循环遍历行星:
- 如果行星的绝对值大于栈顶行星的绝对值:
- 弹出栈顶行星,表示较小的行星被较大的行星撞毁。
- 将当前行星压入栈中。
- 否则:
- 将当前行星压入栈中。
- 如果行星的绝对值大于栈顶行星的绝对值:
- 返回栈中剩余的行星: 这些行星没有被撞毁。
Java 实现
import java.util.Stack;
public class Solution {
public int[] asteroidCollision(int[] asteroids) {
Stack<Integer> stack = new Stack<>();
for (int asteroid : asteroids) {
int absAsteroid = Math.abs(asteroid);
while (!stack.isEmpty() && stack.peek() < absAsteroid) {
stack.pop();
}
if (stack.isEmpty() || asteroid > 0 || stack.peek() < absAsteroid) {
stack.push(asteroid);
}
}
int[] result = new int[stack.size()];
for (int i = stack.size() - 1; i >= 0; i--) {
result[i] = stack.pop();
}
return result;
}
}
自定义比较器
为了判断行星是否会被撞毁,我们需要定义一个自定义比较器:
Comparator<Integer> comparator = (a, b) -> {
int absA = Math.abs(a);
int absB = Math.abs(b);
if (absA == absB) {
return 0;
} else if (absA > absB) {
return -1;
} else {
return 1;
}
};
实例分析
考虑以下行星数组:[-2, -1, 1, 2]
.
- 当我们遇到
-1
时,它比栈顶的-2
小,因此它被弹出。 - 然后我们遇到
1
,它比-2
大,因此它被压入栈中。 - 接下来,我们遇到
2
,它比1
大,因此它也被压入栈中。
最终,栈中剩余的行星为 [-2, 1, 2]
.
结论
通过理解行星碰撞背后的物理直觉,我们可以巧妙地利用栈数据结构和自定义比较器来解决 LeetCode 中的这个难题。这种基于物理定律的算法既优雅又高效,值得深入研究和应用。