【算法】行星碰撞机器人碰撞(栈的使用)

文章目录

  • 行星碰撞
  • 机器人碰撞
    • 补充题目:2731. 移动机器人
  • 参考资料

本文记录了两个使用栈来处理碰撞问题的算法题目。

行星碰撞

https://leetcode.cn/problems/asteroid-collision/
在这里插入图片描述

对于这种题目,各个元素分别会向左或向右移动,可以使用栈模拟碰撞的过程。
由于从左往右进行遍历,因此遍历当前元素时,如果它是向右移动的,就只可能会碰撞到它右边还没有被遍历到的元素,因此可以将其直接放入栈中。
当遍历到向左移动的元素时,它只可能碰撞到当前已经在栈中的元素,需要进行一些处理。

class Solution {public int[] asteroidCollision(int[] asteroids) {Deque<Integer> stk = new ArrayDeque();for (int asteroid: asteroids) {if (asteroid > 0) {		// 向右移动的直接放入栈中stk.push(asteroid);continue;}boolean f = true;  // 记录这个向左的陨石是否还活着while (!stk.isEmpty() && stk.peek() > 0) {if (stk.peek() + asteroid >= 0) {if (stk.peek() + asteroid == 0) stk.pop();f = false;  // 被撞死了break;}f = true;stk.pop();}if (f) stk.push(asteroid);		// 没被撞死就放入栈中}int n = stk.size();		// 由于下面取元素的时候,栈中元素会不断减少,因此需要提前声明 nint[] ans = new int[n];for (int i = 0; i < n; ++i) ans[n - 1 - i] = stk.pop();return ans;}
}

对于这道题目来说,无非只有三种结果:1.没撞过 2.撞过了 3.同归于尽了。分类写 if 即可。

注意在取出栈中元素的过程中,stk.size() 一直在发生变化,因此代码最后不能写成:

for (int i = 0; i < stk.size(); ++i) ans[stk.size() - 1 - i] = stk.pop();

而必须是事先 通过 int n = stk.size() 接收原始结果中元素的个数。

机器人碰撞

https://leetcode.cn/problems/robot-collisions/
题目出自:第 351 场周赛
在这里插入图片描述

这道题目与 行星碰撞 几乎如出一辙,因此代码模板是一样的,差异几乎只存在于 遍历到向左移动的元素时,处理的方式不同。

class Solution {public List<Integer> survivedRobotsHealths(int[] positions, int[] healths, String directions) {int n = positions.length;Integer[] id = new Integer[n];for (int i = 0; i < n; ++i) id[i] = i;  // 记录下标用于排序Arrays.sort(id, (i, j) -> positions[i] - positions[j]); // 按照位置从左往右排序Deque<Integer> stk = new ArrayDeque();for (int i: id) {if (directions.charAt(i) == 'R') {  // 向右,加入栈stk.push(i);continue;}while (!stk.isEmpty()) {int top = stk.peek();if (healths[top] > healths[i]) {    // 栈顶的健康度大healths[top]--;healths[i] = 0;break;}if (healths[top] == healths[i]) {    // 一样大healths[stk.pop()] = 0;healths[i] = 0;break;} // 新来的健康度大healths[stk.pop()] = 0;     healths[i]--;// 不需要将向左移动的机器人加入栈,因为如果它撞完了左边向右移动的,就不会再与任何机器人发生碰撞了}}List<Integer> ans = new ArrayList();for (int h: healths) {if (h != 0) ans.add(h);}return ans;}
}

注意由于机器人的 positions 是乱序的,而我们是需要按照位置的从左到右关系进行遍历,因此常用如下操作对下标进行排序。

Integer[] id = new Integer[n];
for (int i = 0; i < n; ++i) id[i] = i;  // 记录下标用于排序
Arrays.sort(id, (i, j) -> positions[i] - positions[j]); // 按照位置从左往右排序

之所以声明 Integer[] 而不是 int[] 是因为 在 Java 中 int[] 不支持自定义排序。(关于Java 自定义排序可见:【Java】自定义排序)

注意虽然 int[] 不支持,但 int[][] 是支持的,因为 int[][] 的元素是 int[],已经是引用类型了。

补充题目:2731. 移动机器人

2731. 移动机器人
在这里插入图片描述
乍一看这道题目很像是这一类题目,因为两个机器人相撞之后只是改变位置而已,不会对两者的数值或是否存在造成影响。

因此这道题目更像是脑筋急转弯,需要将其相撞转换成——擦肩而过,两者的相撞并不会对结果造成什么影响。既然如此,那么可以把机器人都看成是完全一样的,无法区分。

class Solution {public int sumDistance(int[] nums, String s, int d) {int n = nums.length;final int mod = (int)1e9 + 7;long[] lnums = new long[n];for (int i = 0; i < n; ++i) {lnums[i] = nums[i];if (s.charAt(i) == 'R') lnums[i] += d;else lnums[i] -= d;}Arrays.sort(lnums);long last = 0, ans = 0;for (int i = 1; i < n; ++i) {last = (i * (lnums[i] - lnums[i - 1]) + last) % mod;ans = (ans + last) % mod;}return (int)ans;}
}

关于机器人之间的两两距离如何计算:
在这里插入图片描述

计算时,为了避免溢出,需要取模。(关于取模参见:【算法】数学相关知识总结)


参考资料


栈模拟(Python/Java/C++/Go)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/4087.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

无迹卡尔曼滤波在目标跟踪中的作用(二)

在上一节的内容中&#xff0c;我们介绍了UKF中最重要的内容—无迹变换UT&#xff0c;今天我们将具体介绍UKF是如何实现的。 好了&#xff0c;话不多说&#xff0c;开整&#xff01;&#xff01;&#xff01; UKF算法的实现 我们知道&#xff0c;我们可以使用状态方程和观测方…

kotlin constructor init companion object 与初始化by lazy

kotlin constructor init companion object 与初始化by lazy class MyDemo(private var v: Int) {init {println("init $v")}constructor(m: Int, n: Int) : this(m) {println("constructor $m $n")}//只初始化一次companion object {private var TAG &qu…

死信是什么,如何运用RabbitMQ的死信机制?

系列文章目录 手把手教你&#xff0c;本地RabbitMQ服务搭建&#xff08;windows&#xff09; 消息队列选型——为什么选择RabbitMQ RabbitMQ 五种消息模型 RabbitMQ 能保证消息可靠性吗 推或拉&#xff1f; RabbitMQ 消费模式该如何选择 死信是什么&#xff0c;如何运用Rabbit…

Lesson1-1:OpenCV简介

图像处理 学习目标 了解图像的起源知道数字图像的表示 1 图像的起源 1.1 图像是什么 图像是人类视觉的基础&#xff0c;是自然景物的客观反映&#xff0c;是人类认识世界和人类本身的重要源泉。“图”是物体反射或透射光的分布&#xff0c;“像“是人的视觉系统所接受的图在…

OpenStack(T版)——对象存储(Swift)服务介绍与安装

文章目录 OpenStack(T版)——对象存储(Swift)服务介绍与安装安装和配置(controller)准备安装和配置Swift对象存储服务组件创建账户 Ring创建容器 Ring创建对象 RingSwift 存储系统的主配置文件修改文件属主 安装和配置(compute)准备配置Swift对象存储服务组件 验证(1)加载环境变…

java压测工具 Jmeter初使用

一. 下载及安装教程 1. 有博主总结的很好&#xff0c;这里直接放传送门&#xff1a; 【Jmeter】win 10 / win 11&#xff1a;Jmeter 下载、安装、汉化、新机迁移、版本更新&#xff08;Jmeter 4 以上版本均适用&#xff09; 2. Jmeter 自定义创建桌面快捷方式 3. JMeter插件…

I/O复用的高级应用三——同时处理TCP和UDP服务

截至目前学习&#xff0c;我们讨论过的服务器程序都只监听一个端口。但在实际应用中&#xff0c;有不少服务器程序能同时监听多个端口&#xff0c;比如超级服务inetd和android的调试服务adbd。 从bind系统调用的参数看&#xff0c;一个socket只能与一个socket地址绑定&#xff…

Amdahl定律

Amdahl定律 例:设改进前系统执行时间为3s,改进后系统执行时间为2s 则:加速比3/2 即计算机改进后比改进前快了1.5倍 Amdahl定律影响因素 公式推导 可改进的系统比例为fe,则不可改进的部分比例为(1-fe) 不可改进的部分耗时为T0 * (1- fe) 设改进后部件耗时为T&#xff0c;则…

RISC-V处理器的设计与实现(三)—— 上板验证(基于野火征途Pro开发板)

文章目录 RISC-V处理器的设计与实现&#xff08;一&#xff09;—— 基本指令集_Patarw_Li的博客-CSDN博客 RISC-V处理器的设计与实现&#xff08;二&#xff09;—— CPU框架设计_Patarw_Li的博客-CSDN博客 RISC-V处理器的设计与实现&#xff08;三&#xff09;—— 上板验…

考研算法35天:三元组的最小距离 【双指针,滑动窗口,多路归并】

算法详解 多路归并;多路归并算法从理论到应用&#xff08;易懂&#xff09;_留恋单行路的博客-CSDN博客 多路归并就是将多个已经归并排序排好序的数组再进行排序(不一定是通过归并排序)。 算法题目 这道题就是一般做法是先通过排序将三个数组排好然后再进行三指针求最小。但…

Tuxera NTFS2023Mac电脑免费U盘硬盘读写工具

Mac用户在使用NTFS格式移动硬盘时&#xff0c;会遇到无法写入硬盘的情况。要想解决无法写入的问题&#xff0c;很多人选择使用Mac读写软件。面对市面上“众多”的读写硬盘软件&#xff0c;用户应该怎么选择呢&#xff1f;初次接触移动硬盘的伙伴可能不知道移动硬盘怎么和电脑连…

CAT1模块 EC800M HTTP使用总结记录

分享记录一下 CAT1 模块EC800 HTTP 协议使用流程 ...... by 矜辰所致目录 前言一、基础说明1.1 CAT1 与 4G1.2 EC800M 模块1.3 HTTP 二、开始使用2.1 硬件设计部分2.2 模块上电流程2.3 PDP 上下文2.3.1 什么是 SGSN 和 GGSN &#xff1f; 三、 HTTP 流程3.1 客户端3.1.1 PDP 上…