算法解析:LeetCode——机器人碰撞和最低票价

摘要:本文由葡萄城技术团队原创并首发。转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。

机器人碰撞

问题:

现有 n 个机器人,编号从 1 开始,每个机器人包含在路线上的位置、健康度和移动方向。 给你下标从 0 开始的两个整数数组 positions、healths 和一个字符串 directions(directions[i] 为 ‘L’ 表示 向左 或 ‘R’ 表示 向右)。positions 中的所有整数 互不相同 。 所有机器人以相同速度同时沿给定方向在路线上移动。如果两个机器人移动到相同位置,则会发生 碰撞 。 如果两个机器人发生碰撞,则将 健康度较低 的机器人从路线中 移除 ,并且另一个机器人的健康度 减少 1 。 幸存下来的机器人将会继续沿着与之前 相同 的方向前进。如果两个机器人的健康度相同,则将二者都从路线中移除。 请你确定全部碰撞后幸存下的所有机器人的 健康度 ,并按照原来机器人编号的顺序排列。 即机器人 1 (如果幸存)的最终健康度,机器人 2 (如果幸存)的最终健康度等。 如果不存在幸存的机器人,则返回空数组。 在不再发生任何碰撞后,请你以数组形式,返回所有剩余机器人的健康度(按机器人输入中的编号顺序)。

在这里插入图片描述

示例 :

输入:positions = [3,5,2,6], healths = [10,10,15,12], directions = “RLRL” 输出:[14] 解释:本例中发生 2 次碰撞。首先,机器人 1 和机器人 2 将会碰撞,因为二者健康度相同,二者都将被从路线中移除。接下来,机器人 3 和机器人 4 将会发生碰撞,由于机器人 4 的健康度更小,则它会被移除,而机器人 3 的健康度变为 15 - 1 = 14 。仅剩机器人 3 ,所以返回 [14] 。

提示: 1 <= positions.length == healths.length == directions.length == n <= 105 1 <= positions[i], healths[i] <= 109 directions[i] == ‘L’ 或 directions[i] == ‘R’ positions 中的所有值互不相同。

解决思路

用一个栈存放当前存活的机器人,按位置从左至右(排序后的下标)遍历机器人并判断当前机器人的方向:

1. 如果当前机器人方向是 R,当前机器人推入栈,继续处理下一个机器人;

2.如果方向是 L:

(1)如果栈为空,当前机器人推入栈,继续处理下一个机器人;

(2) 如果栈顶元素方向也是 L,当前机器人推入栈,继续处理下一个机器人;

(3) 比较与栈顶元素的健康度,判断存活哪个:

  • 如果栈顶存活,栈顶机器人健康度减 1,继续处理下一个机器人;
  • 如果当前存活,栈顶弹出,当前机器人健康度减 1,回到 2.3 ;
  • 如果两个都消失,栈顶弹出,继续处理下一个机器人。

3.最后,按position顺序返回stack 中的健康度即可。

代码(JavaScript)

function survivedRobotsHealths(positions: number[], healths: number[], directions: string) : number[] {//用一个栈存放当前存活的机器人let stack: robot[] = [];interface robot {i: number;p: number;h: number;d: string;}let robots: robot[] = [];//从左至右(排序后的下标)遍历机器人并判断当前机器人的方向positions.forEach((v, i) = >robots.push({i: i,p: v,h: healths[i],d: directions[i]}));robots.sort((a, b) = >a.p - b.p);for (let i = 0; i < robots.length;) {/**比较与栈顶元素的健康度,判断存活哪个: 1.如果栈顶存活,栈顶机器人健康度减 1,继续处理下一个机器人;2.如果当前存活,栈顶弹出,当前机器人健康度减 1,回到 2.3 ;3.如果两个都消失,栈顶弹出,继续处理下一个机器人。**/if (stack.length === 0 || robots[i].d === 'R' || (robots[i].d === 'L' && stack[stack.length - 1].d === 'L')) {stack.push(robots[i++]);} else if (stack[stack.length - 1].h === robots[i].h) {stack.pop();i++;} else if (stack[stack.length - 1].h > robots[i].h) {stack[stack.length - 1].h--;i++;} else if (stack[stack.length - 1].h < robots[i].h) {stack.pop();robots[i].h--;}} // console.log(stack);stack.sort((a, b) => a.i - b.i); let ans = []; stack.forEach(v=> ans.push(v.h));             return ans; };

最低票价

问题:

在一个火车旅行很受欢迎的国度,你提前一年计划了一些火车旅行。在接下来的一年里,你要旅行的日子将以一个名为 days 的数组给出。 每一项是一个从 1 到 365 的整数。

火车票有 三种不同的销售方式 :

  • 一张 为期一天 的通行证售价为 costs[0] 美元;
  • 一张 为期七天 的通行证售价为 costs[1] 美元;
  • 一张 为期三十天 的通行证售价为 costs[2] 美元。

通行证允许数天无限制的旅行。 例如,如果我们在第 2 天获得一张 为期 7 天 的通行证,那么我们可以连着旅行 7 天:第 2 天、第 3 天、第 4 天、第 5 天、第 6 天、第 7 天和第 8 天。 返回 你想要完成在给定的列表 days 中列出的每一天的旅行所需要的最低消费 。

示例 1:

输入:days = [1,4,6,7,8,20], costs = [2,7,15]

输出:11

解释: 例如,这里有一种购买通行证的方法,可以让你完成你的旅行计划: 在第 1 天,你花了 costs[0] = $2 买了一张为期 1 天的通行证,它将在第 1 天生效。 在第 3 天,你花了 costs[1] = $7 买了一张为期 7 天的通行证,它将在第 3, 4, …, 9 天生效。 在第 20 天,你花了 costs[0] = $2 买了一张为期 1 天的通行证,它将在第 20 天生效。 你总共花了 $11,并完成了你计划的每一天旅行。

示例 2

输入:days = [1,2,3,4,5,6,7,8,9,10,30,31], costs = [2,7,15]

输出:17

解释: 例如,这里有一种购买通行证的方法,可以让你完成你的旅行计划: 在第 1 天,你花了 costs[2] = $15 买了一张为期 30 天的通行证,它将在第 1, 2, …, 30 天生效。 在第 31 天,你花了 costs[0] = $2 买了一张为期 1 天的通行证,它将在第 31 天生效。 你总共花了 $17,并完成了你计划的每一天旅行。

提示

  • 1 <= days.length <= 365
  • 1 <= days[i] <= 365
  • days 按顺序严格递增
  • costs.length == 3
  • 1 <= costs[i] <= 1000

解决思路
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

代码(JavaScript)

1.暴力递归解法:

//暴力递归解法
function mincostTickets(days: number[], costs: number[]) : number {  return costday(days, costs, 1);
};
function costday(days: number[], costs: number[], day: number) : number {  if (day > days[days.length - 1]) {   return 0;  }  if (day == days[days.length - 1]) {   return Math.min(...costs);  }  if (!days.includes(day)) {   return costday(days, costs, day + 1);  } else {   return Math.min(    costday(days, costs, day + 1) + costs[0],     costday(days, costs, day + 7) + costs[1],     costday(days, costs, day + 30) + costs[2],    )  }
};

问题:

此解法存在重叠子问题和最优子结构

重叠子问题就是F(n)会重复计算,上图中同色的结点

最优子结构就是F(n)的解,可以由子问题F(n+1),F(n+7),F(n+30)的解得到

解决方案:

记录每个子问题f(n)的解,如果后面的计算又要用f(n),则直接取计算结果,避免重复计算:

function mincostTickets(days: number[], costs: number[]) : number {  let fn = [];  return costday(days, costs, 1, fn);
};function costday(days: number[], costs: number[], day: number, fn: number[]) : number {  if (day > days[days.length - 1]) {   return 0;  }  if (day == days[days.length - 1]) {   if (!fn[day]) {    fn[day] = Math.min(...costs);   }   return fn[day];  }  if (!days.includes(day)) {   if (!fn[day]) {    fn[day] = costday(days, costs, day + 1, fn);   }   return fn[day];  } else {   if (!fn[day]) {    fn[day] = Math.min(     costday(days, costs, day + 1, fn) + costs[0],      costday(days, costs, day + 7, fn) + costs[1],      costday(days, costs, day + 30, fn) + costs[2],     )   }   return fn[day];}
};

2.动态规划,自底向上解法

将前面的F(n)换为dp[n],表示从第n天开始后,总共的花费,dp[1]即是问题的解,F(n)是从前往后算,dp是从后往前算,消除递归。

function mincostTickets(days: number[], costs: number[]) : number {  const lastDay = days[days.length - 1]; let dp = new Array(lastDay + 30 + 1).fill(0);  for (let i = lastDay; i >= 1; i--) {   if (days.includes(i)) {//此处还可以优化,将所有days放到set中判断day是否存在dp[i] = Math.min(dp[i + 1] + costs[0], dp[i + 7] + costs[1], dp[i + 30] + costs[2]);   } else {    dp[i] = dp[i + 1];   }  }  return dp[1];
};

总结

以上就是机器人碰撞和最低票价两个问题的解法,除此之外,如果您想了解更多关于JavaScript的资料,欢迎访问这篇学习指南,无论是初学者还是有经验的专业人士,该帮助手册都将为您提供有价值的指导和帮助。

扩展链接:

从表单驱动到模型驱动,解读低代码开发平台的发展趋势

低代码开发平台是什么?

基于分支的版本管理,帮助低代码从项目交付走向定制化产品开发

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

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

相关文章

ubuntu 安装jdk21开发环境

下载 wget https://download.oracle.com/java/21/latest/jdk-21_linux-x64_bin.tar.gz 第二步&#xff1a;解压 tar -zxvf jdk-21_linux-x64_bin.tar.gz 第三步&#xff1a;移动 jdk-21 目录到 /usr/local/jdk21 第四步&#xff1a;配置环境变量 sudovim/etc/profile vim/etc/…

Excel 的单元格内容和单元格格式

文章目录 单元格内容单元格格式常规格式数字格式 单元格内容 文本&#xff1a;只要不是纯数字&#xff0c;Excel 都默认是文本格式。 在 Excel 中&#xff0c;逻辑值只有两个&#xff1a;True 和 False。 全选一片区域&#xff0c;按 Delet 键删除内容时&#xff0c;确实可以删…

VTK编译解决CMake的“could not find any instance of Visual Studio”的问题

1、在配置VTK源码编译的过程中&#xff0c;遇到报错 “CMake的“could not find any instance of Visual Studio””,cmake在编程找不到vs2017路径或者配置不全。 解决方案&#xff1a; 安装“Visual Studio Installer”&#xff1b; 1.检查是否安装 “使用C的桌面开发” 2.检…

ACP.复盘方法

复盘要怎么做的有水准&#xff0c;让领导满意&#xff0c;方式方法很重要。今天给你们安利5种复盘方法&#xff0c;保准你省事&#xff0c;领导还满意。 一、KPT复盘法 7月份年中一直在做和复盘相关的事&#xff0c;像公司的OKR复盘、年中战略规划&#xff0c;不过日常很多生…

力扣刷题 day43:10-13

1.完全平方数 给你一个整数 n &#xff0c;返回 和为 n 的完全平方数的最少数量 。 完全平方数 是一个整数&#xff0c;其值等于另一个整数的平方&#xff1b;换句话说&#xff0c;其值等于一个整数自乘的积。例如&#xff0c;1、4、9 和 16 都是完全平方数&#xff0c;而 3 …

SOLIDWORKS® 2024 新功能 - 3D CAD

1、 先前版本的兼容性 • 利用您订阅的 SOLIDWORKS&#xff0c;可将您的 SOLIDWORKS 设计作品保存为旧版本&#xff0c;与使用旧版本 SOLIDWORKS 的供应商无缝协作。 • 可将零件、装配体和工程图保存为新版本前两年之内的SOLIDWORKS 版本。 优点&#xff1a; 即使其他用户正…

内存空间的分配与回收之连续分配管理方式

1.连续分配管理方式 连续分配:指为用户进程分配的必须是一个连续的内存空间。 1.单一连续分配 在单一连续分配方式中&#xff0c;内存被分为系统区和用户区。系统区通常位于内存的低地址部分&#xff0c;用于存放操作系统相关数据;用户区用于存放用户进程相关数据。内存中只…

多服务器云探针源码(服务器云监控)/多服务器多节点_云监控程序python源码

源码简介&#xff1a; 多服务器云探针源码(服务器云监控),支持python多服务器多节点&#xff0c;云监控程序源码。它是一款很实用的云探针和服务器云监控程序源码。使用它可以帮助管理员能够快速监控和管理各种服务器和节点&#xff0c;实用性强。 源码链接&#xff1a; 网盘…

【机器学习】sklearn特征选择(feature selection)

文章目录 特征工程过滤法&#xff08;Filter&#xff09;方差过滤相关性过滤卡方过滤F验表互信息法小结 嵌入法&#xff08;Embedded&#xff09;包装法&#xff08;Wrapper&#xff09; 特征工程 特征提取(feature extraction)特征创造(feature creation)特征选择(feature se…

lv8 嵌入式开发-网络编程开发 17 套接字属性设置

1 基本概念 设置套接字的选项对套接字进行控制除了设置选项外&#xff0c;还可以获取选项选项的概念相当于属性&#xff0c;所以套接字选项也可说是套接字属性有些选项&#xff08;属性&#xff09;只可获取&#xff0c;不可设置&#xff1b;有些选项既可设置也可获取 2 选项…

Ansible概述和模块解释

一、Ansible概述 Ansible介绍 Ansible是一个基于Python开发的配置管理和应用部署工具&#xff0c;现在也在自动化管理领域大放异彩。它融合了众多老牌运维工具的优点&#xff0c;Pubbet和Saltstack能实现的功能&#xff0c;Ansible基本上都可以实现。 Ansible能做什么 Ansi…

呼吁社区共同维护Sui品牌和商标

Sui社区成员可以通过举报Sui商标和品牌资产的不当使用来帮助保护网络的信誉。Sui商标政策解释了logo和名称的可接受和不可接受的使用方式。这些展示代表Sui面向公众&#xff0c;而善意行为者的正确使用有助于维护Sui的声誉。 Sui网络在公众中享有良好声誉&#xff0c;Sui社区都…

GEO生信数据挖掘(七)差异基因分析

上节&#xff0c;我们使用结核病基因数据&#xff0c;做了一个数据预处理的实操案例。例子中结核类型&#xff0c;包括结核&#xff0c;潜隐进展&#xff0c;对照和潜隐&#xff0c;四个类别。本节延续上个数据&#xff0c;进行了差异分析。 差异分析 计算差异指标step12 加载…

API攻防-接口安全SOAPOpenAPIRESTful分类特征导入项目联动检测

文章目录 概述什么是接口&#xff1f; 1、API分类特征SOAP - WSDLWeb services 三种基本元素&#xff1a; OpenApi - Swagger UISpringboot Actuator 2、API检测流程Method&#xff1a;请求方法URL&#xff1a;唯一资源定位符Params&#xff1a;请求参数Authorization&#xff…

阿里云r7服务器内存型CPU采用

阿里云服务器ECS内存型r7实例是第七代内存型实例规格族&#xff0c;CPU采用第三代Intel Xeon可扩展处理器&#xff08;Ice Lake&#xff09;&#xff0c;基频2.7 GHz&#xff0c;全核睿频3.5 GHz&#xff0c;计算性能稳定&#xff0c;CPU内存比1:8&#xff0c;2核16G起步&#…

NSIDC定义的海冰相关概念

文章目录 相关概念Matlab绘图结果展示 相关概念 NSIDC 表示 “National Snow and Ice Data Center”&#xff0c;即美国国家雪和冰数据中心。NSIDC 是一个位于美国科罗拉多大学波尔得分校的研究中心&#xff0c;致力于收集、管理和分发全球雪和冰的科学数据。 Matlab绘图 cl…

2015架构真题(五十)

供应链中信息流覆盖了供应商、制造商和分销商&#xff0c;信息流分为需求信息流和供应信息流&#xff0c;&#xff08;&#xff09;属于需求信息流&#xff0c;&#xff08;&#xff09;属于供应信息流。 库存记录生产计划商品入库单提货发运单 客户订单采购合同完工报告单销售…

迅为RK3568开发板Scharr滤波器算子边缘检测

本小节代码在配套资料“iTOP-3568 开发板\03_【iTOP-RK3568 开发板】指南教程\04_OpenCV 开发配套资料\33”目录下&#xff0c;如下图所示&#xff1a; 在 Sobel 算子算法函数中&#xff0c;如果设置 ksize-1 就会使用 3x3 的 Scharr 滤波器。Scharr 算子是 Soble 算子在 ksize…

leetcode oj

150. 逆波兰表达式求值 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a;定义一个名为 Solution 的类&#xff0c;并在其中定义了一个名为 evalRPN 的公共函数。这个函数接受一个由字符串组成的向量 tokens 作为输入&#xff0c;并返回一个整数。 在代码中&#xff0…

【C++初阶】关键字命名空间缺省函数函数重载入门必看!!!超详解!!!

主页点击直达&#xff1a;个人主页 我的小仓库&#xff1a;代码仓库 C语言偷着笑&#xff1a;C语言专栏 数据结构挨打小记&#xff1a;初阶数据结构专栏 Linux被操作记&#xff1a;Linux专栏 LeetCode刷题掉发记&#xff1a;LeetCode刷题 算法&#xff1a;算法专栏 C头…