LeetCode——735.行星碰撞
给定一个整数数组 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] 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/asteroid-collision
一
方法:栈
如果不会发生碰撞那么一排小行星是处于稳定的状态。若在右边增加一个新的小行星后,在它再次稳定之前,可能会发生更多的碰撞,而所有的这些碰撞(如果发生的话)都必须从右到左发生。这种情况非常适合用栈解决。
算法:
假设栈中顶部元素为 top,一个新的小行星 new 进来了。如果 new 向右移动(new>0),或者 top 向左移动(top<0),则不会发生碰撞。
否则,如果 abs(new) < abs(top),则新小行星 new 将爆炸;如果 abs(new) == abs(top),则两个小行星都将爆炸;如果 abs(new) > abs(top),则 top 小行星将爆炸(可能还会有更多小行星爆炸,因此我们应继续检查)。
python
class Solution(object):
def asteroidCollision(self, asteroids):
ans = []
for new in asteroids:
while ans and new < 0 < ans[-1]:
if ans[-1] < -new:
ans.pop()
continue
elif ans[-1] == -new:
ans.pop()
break
else:
ans.append(new)
return ans
java
class Solution {
public int[] asteroidCollision(int[] asteroids) {
Stack<Integer> stack = new Stack();
for (int ast: asteroids) {
collision: {
while (!stack.isEmpty() && ast < 0 && 0 < stack.peek()) {
if (stack.peek() < -ast) {
stack.pop();
continue;
} else if (stack.peek() == -ast) {
stack.pop();
}
break collision;
}
stack.push(ast);
}
}
int[] ans = new int[stack.size()];
for (int t = ans.length - 1; t >= 0; --t) {
ans[t] = stack.pop();
}
return ans;
}
}
复杂度分析
时间复杂度:O(N),其中 N 是行星的数量。
空间复杂度:O(N),ans 使用的空间。
二
这道题用一个数组来模拟行星碰撞,正数代表行星向右移动,负数表示向左移动,绝对值大小表示行星的质量,如果两个相邻的行星相向移动会碰撞,质量大的行星会完好无损的保存,质量小的就会灰飞烟灭。那么博主最开始想的方法就是按照题目要求来一个一个的处理,我们先把给定的数组放到结果res中,然后进行while循环,如果此时结果res中的数字个数小于等于1个,直接返回即可,没有可碰撞的了。否则我们建立一个临时数组t,把结果res中的首元素放到t中,然后从第二个数字开始遍历结果res,如果此时t为空了,或者当前数字大于0而t数组最后一个数字小于0(此时两个行星向相反方向运动,不会相撞),或者两个数字的符号相同(此时两个行星向同一个方向运动,不会相撞),这三种情况下都把当前数字res[i]加到数组t中;那么剩下的情况就是两个行星相向运动了,如果两个数字相加等于0,则说明两个行星质量相同,且相向运动,则一起消失,我们将数组t中最后一个数字移除;如果当前数字小于0,且两个数字相加小于0,那么此时相撞后会留下质量大的行星,我们将数组t的最后一个数字赋值为res[i]即可。for循环之和,如果数组t和结果res的大小相等,说明此时状态已经稳定了,我们直接break,否则就把数组t赋值给结果res并继续循环,参见代码如下:
解法一:
class Solution {
public:
vector<int> asteroidCollision(vector<int>& asteroids) {
vector<int> res = asteroids;
while (true) {
if (res.size() <= 1) return res;
vector<int> t{res[0]};
for (int i = 1; i < res.size(); ++i) {
if (t.empty() || (res[i] > 0 && t.back() < 0) || res[i] * t.back() > 0) {
t.push_back(res[i]);
} else if (res[i] + t.back() == 0) {
t.pop_back();
} else if (res[i] < 0 && res[i] + t.back() < 0) {
t.back() = res[i];
}
}
if (t.size() == res.size()) break;
else res = t;
}
return res;
}
};
实际上我们可以写的更加简洁一些,我们遍历所有的数字,如果当前数字是正数的话,我们直接加入结果res;否则我们遇到的都是负数,如果结果res为空,或者结果res的最后一个数字小于0(此时两个行星同时向左运动),直接将当前数字加入结果res;如果结果res的最后一个数字(此时为正数)小于当前数字的绝对值,说明碰撞后消失了,那么我们将i自减一个,然后将res最后一个数字移除,这样下次遍历的时候还是这个质量大的行星。如果两个质量相等,那么直接移除res最后一个数字,此时两个行星都消失了,参见代码如下:
解法二:
class Solution {
public:
vector<int> asteroidCollision(vector<int>& asteroids) {
vector<int> res;
for (int i = 0; i < asteroids.size(); ++i) {
if (asteroids[i] > 0) {
res.push_back(asteroids[i]);
} else if (res.empty() || res.back() < 0) {
res.push_back(asteroids[i]);
} else if (res.back() <= -asteroids[i]) {
if (res.back() < -asteroids[i]) --i;
res.pop_back();
}
}
return res;
}
};
LeetCode——735.行星碰撞的更多相关文章
- Java实现 LeetCode 735 行星碰撞(栈)
735. 行星碰撞 给定一个整数数组 asteroids,表示在同一行的行星. 对于数组中的每一个元素,其绝对值表示行星的大小,正负表示行星的移动方向(正表示向右移动,负表示向左移动).每一颗行星以相 ...
- [LeetCode] Asteroid Collision 行星碰撞
We are given an array asteroids of integers representing asteroids in a row. For each asteroid, the ...
- [LeetCode] 735. Asteroid Collision
行星碰撞. 题意是给一个数组 asteroids,表示在同一行的行星.对于数组中的每一个元素,其绝对值表示行星的大小,正负表示行星的移动方向(正表示向右移动,负表示向左移动).每一颗行星以相同的速度移 ...
- [Swift]LeetCode735. 行星碰撞 | Asteroid Collision
We are given an array asteroids of integers representing asteroids in a row. For each asteroid, the ...
- Swift LeetCode 目录 | Catalog
请点击页面左上角 -> Fork me on Github 或直接访问本项目Github地址:LeetCode Solution by Swift 说明:题目中含有$符号则为付费题目. 如 ...
- C#LeetCode刷题-栈
栈篇 # 题名 刷题 通过率 难度 20 有效的括号 C#LeetCode刷题之#20-有效的括号(Valid Parentheses) 33.0% 简单 42 接雨水 35.6% 困难 71 简 ...
- C语言每日一题
66. 加一 /** * Note: The returned array must be malloced, assume caller calls free(). */ /* 从后向前(从个位)开 ...
- 游戏编程算法与技巧 Game Programming Algorithms and Techniques (Sanjay Madhav 著)
http://gamealgorithms.net 第1章 游戏编程概述 (已看) 第2章 2D图形 (已看) 第3章 游戏中的线性代数 (已看) 第4章 3D图形 (已看) 第5章 游戏输入 (已看 ...
- 【LeetCode】735. Asteroid Collision 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 栈 日期 题目地址:https://leetcode ...
随机推荐
- 【PentestBox】rubygems.rb erorr
PentestBox可以在windows下运行一些Linux系统命令,但仍然基于windows. 若使用msfconsole或者gem命令是出现: internal:gem_prelude:1:in ...
- 7 ~ express ~ body-parser 模块的使用
一,安装 : npm install body-parser 二,加载 : var bodyParser = require('body-parser') 三,配置 : https://github. ...
- JAVAEE 和项目开发(第二课:HTTP协议的特点和交互流程)
HTTP 的概念和介绍 概念:超文本传输协议(Hyper Text Transfer Protocol) 作用:规范了浏览器和服务器的数据交互 特点: 简单快速:客户向服务器请求服务时,只需传送请求方 ...
- 第二阶段scrum-3
1.整个团队的任务量: 2.任务看板: 会议照片: 产品状态: 前端制作完成,数据库正在配置
- UVALive 6763 / CSU 1446
今天比赛的时候拿到的第一道题,其实挺简单的,求两等差序列中相同元素的个数,我想了一下就觉得,只要找到了第一个相等的点,然后后面求最大公约数就可以直接得到结果了 网上叫什么拓展欧几里得,我反正是按照我们 ...
- jdk8安装
==安装jdk1.8== [root@ycj ~]# mkdir -p /usr/local/src/jdk //创建目录 [root@ycj jdk]# cd /usr/local/src/jdk ...
- Spring装配Bean的一些高级技巧
一.使用@Profile注解来实现在不同环境下创建不同的Bean 实现方式:将不同的Bean定义整理到对应环境的Profile中,当应用部署到不同的环境时(开发环境或者是QA环境或者是生产环境),激活 ...
- oracle(8)视图和查询数据库对象方法
视图 view 视图是数据库的对象之一. 视图也叫做虚表,既虚拟表,本质是对应一条select 语句, select语句的结果集赋予一个名字就是视图的名字. 作用: 1.可以简化复杂的查询 2.可以限 ...
- Window Nginx安装
1.下载Nginx 下载地址:http://nginx.org/en/download.html 我这里下载的版本是: nginx/Windows-1.12.2 2.解压Nginx 把下载下来的zip ...
- 给普通用户加sudo权限
系统环境:centos 7.0 引文:在实验室的服务器上给每个人分配了一个账号,但是有的时候普通用户需要使用root权限,比如装一些软件之类的.下面介绍怎么给普通用户添加sudo命令权限. 前提: s ...