当前位置: 首页 > news >正文

算法练习-成功之后不许掉队

题目由实际的业务抽象而来。

题目描述
有一排任务,每个任务有一个状态:
0 待处理 1 取消 2 执行中3 执行成功 4 执行失败
业务规定
状态为 1(取消)的任务既不会触发重跑,也不会被重跑,就当它不存在。只要前面出现过任何一次非成功(即 0、2、4),那么后面再出现的所有“成功”(3)都必须重新执行。
现在请你返回本次需要重新执行的第一个任务下标;如果无需执行,返回 -1。
输入格式
第一行一个整数 n (0 ≤ n ≤ 10⁶)。
第二行 n 个整数,第 i 个数表示第 i 个任务的状态。
输出格式
一个整数:第一个需要重跑的任务下标;没有就输出 -1。
示例
输入 1
4
4 3 3 3
输出 1
解释
下标 0 是失败(非成功),后面所有成功都要重跑,因此第一个要重跑的是下标 1。
输入 2
5
3 3 4 3 3
输出 2
解释
下标 2 第一次出现非成功,其后所有成功都要重跑,所以答案 2。
输入 3
3
1 1 3
输出 -1
解释
只有取消和成功,没有非成功出现,无需执行。
数据范围
n ≤ 10⁶,保证 O(n) 一次扫描即可。
提示
用“红绿灯”思想:
绿灯:还没遇到非成功。
红灯:已遇到非成功,此后一旦出现成功就要重跑。
全程只需两个变量,额外空间 O(1)。

代码实现如下:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;public class TaskExecutor {/* ===================== 模型(同上,省略) ===================== */public enum Status {待处理, 取消, 执行中, 执行成功, 执行失败}public static class Task {private Integer id;private Status status;public Task(Integer id, Status status) {this.id = id;this.status = status;}public Integer getId() {return id;}public Status getStatus() {return status;}public void setStatus(Status status) {this.status = status;}@Overridepublic String toString() {return "Task#" + id + "(" + status + ")";}}/* ===================== 执行器 ===================== */public static class SimpleTaskExecutor {public void process(List<Task> taskList) {if (taskList == null || taskList.isEmpty()) return;// 1. 按id升序taskList.sort(Comparator.comparing(Task::getId));// 2. 找到“第一个需要被重新执行”的索引int start = findFirstNeedReExec(taskList);// 3. 从该索引开始顺序执行for (int i = start; i < taskList.size(); i++) {Task t = taskList.get(i);if (t.getStatus() == Status.取消) continue;   // 明确取消就跳过t.setStatus(Status.执行中);System.out.println("开始执行 " + t);boolean success = doBiz(t);t.setStatus(success ? Status.执行成功 : Status.执行失败);System.out.println("执行完毕 " + t);}System.out.println("全部处理完成");}/*** 核心:找“第一个需要被重新执行”的任务* 规则:只要前面出现过非成功,后面再出现成功,则这条成功也要重跑,* 返回这段区间里的第一个任务索引。*/private static int findFirstNeedReExec(List<Task> list) {int startIndex = list.size(); // 默认:不跑for (int i = 0; i < list.size(); i++) {Status s = list.get(i).getStatus();if (s == Status.取消) continue;if (s != Status.执行成功 && startIndex == list.size()) {startIndex = i;   // 只记录第一次}}return startIndex;}private boolean doBiz(Task t) {try {Thread.sleep(500);} catch (InterruptedException ignore) {}return Math.random() > 0.3; // 70% 成功率}}/* ===================== 测试 ===================== */public static void main(String[] args) {List<Task> list = new ArrayList<>();// 构造场景:成功前面有非成功list.add(new Task(1, Status.执行失败));list.add(new Task(2, Status.执行成功)); list.add(new Task(3, Status.执行成功));  list.add(new Task(4, Status.执行成功));new SimpleTaskExecutor().process(list);}
}

实现思路一句话:
“扫一遍,遇见非成功就亮红灯,红灯后再遇到第一个成功就是要重跑的开头;如果一直没亮红灯,就返回第一个非成功即可。”


变量解释(两个布尔/整数就够)

变量含义
metFail布尔,是否已亮红灯(即前面出现过 0/2/4 且未被取消)。
first整数,答案下标,初始 -1。

遍历逻辑(伪代码,与题目状态编码一致)

metFail = False
first   = -1
for i in 0..n-1:s = status[i]if s == 1:            # 取消当空气,直接跳过continueif s != 3:            # 0、2、4 都是非成功metFail = Trueif first == -1:   # 记录第一个非成功位置first = ielse:                 # s == 3 成功if metFail:       # 红灯已亮,这条成功必须重跑if first == -1:first = i  # 理论上不会进,保险break          # 找到“第一段”就可以提前退出

循环结束后:

  • 如果 first != -1 → 返回 first
  • 否则全程无非成功 → 返回 -1

正确性证明

  1. 没亮红灯(metFail == False
    说明前面只有取消或成功,按规则无需重跑;此时 first 保持 -1,符合要求。
  2. 亮红灯后(metFail == True
    • 若当前是非成功,我们把它记为 first,继续往后扫。
    • 一旦遇到成功,它就是“红灯后的第一个成功”,按规则必须重跑,且它前面的非成功已经被记录在 first,所以直接 break 返回即可。

因此 first 总是第一个需要被重新执行的任务下标。


复杂度
时间:O(n) —— 每个元素常数时间,最多扫一遍。
空间:O(1) —— 只用到两个变量。

http://www.dtcms.com/a/607368.html

相关文章:

  • 连云港做网站哪里好什么叫社交电商平台
  • 重庆游戏网站开发公司yande搜索引擎官网入口
  • AI 写的json快速构建-还原网站
  • 广东省省考备考(第一百四十九天11.13)——资料分析、数量关系(强化训练)
  • 做网站如何挂支付系统有哪些企业可以做招聘的网站有哪些内容
  • 网站 seo 优化建议达人室内设计网怎么免费注册
  • 5G的三大关键技术介绍
  • 360免费做网站上海网站制作网络推广
  • 零代码+三维仿真!实现自然灾害的可视化模拟与精准预警
  • 网站怎么做排查修复网络营销是怎么发展的
  • Linux用户和组管理实验
  • 5.6、Python-正则表达式
  • 软件外包公司有哪些深圳优化公司找高粱seo服务
  • 使用fiftyone去浏览coco数据集
  • 珠海模板建站平台网站建设个人先进材料
  • 如何在需求理解偏差后进行修正与再确认
  • 网站实现功能云南百度小程序开发
  • 无锡新区建设环保局网站计算机类哪个专业最吃香
  • 什么网站可以做宝宝相册wordpress取自定义字段
  • 网站收录问题网络宣传的方法渠道
  • 摄影网站制作步骤html企业网络组网
  • HCIP笔记4--OSPF域内路由
  • 网站建设岗位主要做什么无锡本地做网站
  • 网站建设答案企业网站的建设与维护
  • 南昌网站快速排名提升沛县网络营销是什么
  • 网站建设图片怎么切群晖wordpress固定链接404
  • 李氏牛仔网站建设风格海外广告投放是干嘛的
  • ipv6简介
  • Vue3 中使用富文本编辑器 wangeditor
  • vue做的个人网站WordPress直接填写密码