【数据结构和算法】小行星碰撞

2024-02-09 10:30

本文主要是介绍【数据结构和算法】小行星碰撞,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

其他系列文章导航

Java基础合集
数据结构与算法合集

设计模式合集

多线程合集

分布式合集

ES合集


文章目录

其他系列文章导航

文章目录

前言

一、题目描述

二、题解

2.1 什么情况会用到栈

2.2 方法一:模拟 + 栈

三、代码

3.1 方法一:模拟 + 栈

四、复杂度分析

4.1 方法一:模拟 + 栈


前言

这是力扣的 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 。

提示:

  • 2 <= asteroids.length <= 104
  • -1000 <= asteroids[i] <= 1000
  • asteroids[i] != 0

二、题解

2.1 什么情况会用到栈

栈是一种数据结构,其特点是后进先出(Last In First Out,LIFO)。在算法中,栈在很多情况下是非常有用的,下面是一些常见的情况:

  1. 括号匹配:当你有一个包含括号的字符串,并且你想要检查这个字符串中的括号是否匹配,你可以使用栈。从左到右扫描字符串,如果遇到左括号(如“(”,“{”或“[”),则将其压入栈。如果遇到右括号,则从栈顶弹出一个元素并检查它们是否匹配。如果它们不匹配,那么这个字符串就不是有效的。
  2. 深度优先搜索(DFS):在图的遍历中,栈经常被用于实现深度优先搜索。首先,将起始节点压入栈。然后,当栈不为空时,弹出栈顶元素并访问它。对于每个刚刚访问过的节点,将其未被访问过的邻居节点压入栈。
  3. 函数调用:在计算机程序的执行中,函数调用通常使用栈来管理。当一个函数被调用时,它的参数和局部变量被压入栈。当函数执行结束时,这些数据从栈中弹出。
  4. 文本编辑器中的撤销/重做功能:许多文本编辑器使用撤销/重做功能来允许用户撤销他们最近所做的更改。这些功能通常使用一个操作栈,每个操作(例如插入或删除文本)都被压入栈。用户可以多次撤销,每次撤销都从栈中弹出并反转一个操作。
  5. 解析语法:在编译原理中,栈被广泛用于解析语法。例如,在解析一个算术表达式时,你可以使用栈来保持追踪括号和操作符的优先级。

这只是栈在算法中的一些应用,实际上还有很多其他的应用场景。

2.2 方法一:模拟 + 栈

思路与算法:

由于碰撞抵消总是从相邻行星之间发生,我们可以使用「栈」来模拟该过程。

从前往后处理所有的 asteroids[i] ,使用栈存储当前未被抵消的行星,当栈顶元素方向往右,当前 asteroids[i] 方向往左时,会发生抵消操作,抵消过程根据规则进行即可。

用到变量 ok 的 true 和 false 来表示待插入栈的元素是否还大于栈顶元素。

最后把栈内元素再放入 int[] 中。


三、代码

3.1 方法一:模拟 + 栈

Java版本:

class Solution {public static int[] asteroidCollision(int[] asteroids) {ArrayDeque<Integer> deque = new ArrayDeque<>();for (int i : asteroids) {boolean ok = true;while (ok && !deque.isEmpty() && deque.peekLast() > 0 && i < 0) {int a = deque.peekLast(), b = -i;if (a <= b) deque.pollLast();if (a >= b) ok = false;}if (ok) deque.addLast(i);}int n = deque.size();int[] res = new int[n];while(!deque.isEmpty()) res[--n]=deque.pollLast();return res;}
}

C++版本:

class Solution {
public:static vector<int> asteroidCollision(vector<int>& asteroids) {deque<int> deque;for (int i : asteroids) {bool ok = true;while (ok && !deque.empty() && deque.back() > 0 && i < 0) {int a = deque.back(), b = -i;if (a <= b) deque.pop_back();if (a >= b) ok = false;}if (ok) deque.push_back(i);}vector<int> res(deque.begin(), deque.end());return res;}
};

Python版本:

from collections import dequeclass Solution:def asteroidCollision(self, asteroids: List[int]) -> List[int]:deque = deque()for i in asteroids:ok = Truewhile ok and deque and deque[-1] > 0 and i < 0:a, b = deque[-1], -iif a <= b: deque.pop()if a >= b: ok = Falseif ok: deque.append(i)return list(deque)

Go版本:

package mainimport "fmt"func asteroidCollision(asteroids []int) []int {var stack []intfor _, i := range asteroids {ok := truefor ok && len(stack) > 0 && stack[len(stack)-1] > 0 && i < 0 {a, b := stack[len(stack)-1], -iif a <= b {stack = stack[:len(stack)-1]}if a >= b {ok = false}}if ok {stack = append(stack, i)}}return stack
}func main() {asteroids := []int{5, 10, -5}fmt.Println(asteroidCollision(asteroids))
}

四、复杂度分析

4.1 方法一:模拟 + 栈

  • 时间复杂度:O(n)。
  • 空间复杂度:O(n)。

这篇关于【数据结构和算法】小行星碰撞的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/693956

相关文章

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

C#数据结构之字符串(string)详解

《C#数据结构之字符串(string)详解》:本文主要介绍C#数据结构之字符串(string),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录转义字符序列字符串的创建字符串的声明null字符串与空字符串重复单字符字符串的构造字符串的属性和常用方法属性常用方法总结摘

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

如何通过Golang的container/list实现LRU缓存算法

《如何通过Golang的container/list实现LRU缓存算法》文章介绍了Go语言中container/list包实现的双向链表,并探讨了如何使用链表实现LRU缓存,LRU缓存通过维护一个双向... 目录力扣:146. LRU 缓存主要结构 List 和 Element常用方法1. 初始化链表2.

golang字符串匹配算法解读

《golang字符串匹配算法解读》文章介绍了字符串匹配算法的原理,特别是Knuth-Morris-Pratt(KMP)算法,该算法通过构建模式串的前缀表来减少匹配时的不必要的字符比较,从而提高效率,在... 目录简介KMP实现代码总结简介字符串匹配算法主要用于在一个较长的文本串中查找一个较短的字符串(称为

通俗易懂的Java常见限流算法具体实现

《通俗易懂的Java常见限流算法具体实现》:本文主要介绍Java常见限流算法具体实现的相关资料,包括漏桶算法、令牌桶算法、Nginx限流和Redis+Lua限流的实现原理和具体步骤,并比较了它们的... 目录一、漏桶算法1.漏桶算法的思想和原理2.具体实现二、令牌桶算法1.令牌桶算法流程:2.具体实现2.1

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系