第432场周赛:跳过交替单元格的之字形遍历、机器人可以获得的最大金币数、图的最大边权的最小值、统计 K 次操作以内得到非递减子数组的数目

Q1、跳过交替单元格的之字形遍历

1、题目描述

给你一个 m x n 的二维数组 grid,数组由 正整数 组成。

你的任务是以 之字形 遍历 grid,同时跳过每个 交替 的单元格。

之字形遍历的定义如下:

  • 从左上角的单元格 (0, 0) 开始。
  • 在当前行中向 移动,直到到达该行的末尾。
  • 下移到下一行,然后在该行中向 移动,直到到达该行的开头。
  • 继续在行间交替向右和向左移动,直到所有行都被遍历完。

**注意:**在遍历过程中,必须跳过每个 交替 的单元格。

返回一个整数数组 result,其中包含按 顺序 记录的、且跳过交替单元格后的之字形遍历中访问到的单元格值。

2、解题思路

  1. 方向交替:

    • 遍历过程中,偶数行从左到右,奇数行从右到左。可以使用 reverse 方法在遍历奇数行时反转数组。
  2. 跳过单元格:

    • 通过布尔变量 flag 来控制是否访问当前单元格。

    • 每访问一个单元格后,将 flag 取反,跳过下一个单元格。

  3. 结果记录:

    • 将每次访问到的单元格值存入结果数组 ret 中。

3、代码实现

class Solution {
public:vector<int> zigzagTraversal(vector<vector<int>>& grid) {vector<int> ret;  // 存储最终结果数组bool flag = true; // 标记是否访问当前单元格, 初始为访问// 遍历每一行for (int i = 0; i < grid.size(); ++i) {// 当前行的引用, 便于操作auto& row = grid[i];// 奇数行需要反转以实现从右到左的遍历if (i % 2 == 1) {ranges::reverse(row); // 使用 C++20 的 ranges::reverse 反转行}// 遍历当前行的所有元素for (int x : row) {// 如果标记为 true, 则访问当前单元格if (flag) {// 将当前单元格值加入结果数组ret.push_back(x);}// 取反标记, 跳过下一个单元格flag = !flag;}}return ret; // 返回最终结果}
};

在这里插入图片描述

4、复杂度分析

时间复杂度分析

  1. 行遍历:
    • 外层 for 循环遍历所有 m 行。
  2. 行内遍历:
    • 每行遍历 n 个元素,共访问 m × n m\times n m×n 个单元格。
    • 奇数行反转操作的复杂度为 O(n)

总时间复杂度: O ( m × n ) O(m \times n) O(m×n)

空间复杂度分析

  1. 额外空间:
    • 结果数组 ret 存储跳过单元格后的值,大小最多为 ⌈ m × n / 2 ⌉ \lceil m \times n / 2 \rceil m×n/2
    • 反转操作在原地完成,不需要额外空间。

总空间复杂度: O ( m × n ) O(m \times n) O(m×n)(存储结果数组的空间)


Q2、机器人可以获得的最大金币数

1、题目描述

给你一个 m x n 的网格。一个机器人从网格的左上角 (0, 0) 出发,目标是到达网格的右下角 (m - 1, n - 1)。在任意时刻,机器人只能向右或向下移动。

网格中的每个单元格包含一个值 coins[i][j]

  • 如果 coins[i][j] >= 0,机器人可以获得该单元格的金币。
  • 如果 coins[i][j] < 0,机器人会遇到一个强盗,强盗会抢走该单元格数值的 绝对值 的金币。

机器人有一项特殊能力,可以在行程中 最多感化 2个单元格的强盗,从而防止这些单元格的金币被抢走。

**注意:**机器人的总金币数可以是负数。

返回机器人在路径上可以获得的 最大金币数

2、解题思路

我们可以使用动态规划 (Dynamic Programming, DP) 来解决问题。采用一个三维 dp 数组,其中 dp[i][j][k] 表示机器人到达网格单元 (i, j) 时,感化了 k 个强盗后能够获得的最大金币数。

动态规划转移方程

  1. 定义状态

    • dp[i][j][k]:到达单元 (i, j),感化了 k 个强盗后的最大金币数。
    • k 的范围为 [0, 2],表示机器人最多能感化 2 个强盗。
  2. 状态转移

    • 假设当前单元格的金币值为 coins[i][j]
      • 如果从 上方 (i-1, j) 转移到 (i, j)
        • 如果不感化强盗,dp[i][j][k] = max(dp[i][j][k], dp[i-1][j][k] + coins[i][j])
        • 如果感化强盗(即 coins[i][j] < 0 且剩余感化次数 k > 0),dp[i][j][k] = max(dp[i][j][k], dp[i-1][j][k-1])
      • 如果从 左侧 (i, j-1) 转移到 (i, j)
        • 与从上方的情况类似。
  3. 初始条件

    • 对于起点 (0, 0)
      • 如果 coins[0][0] >= 0,金币数为 coins[0][0]
      • 如果 coins[0][0] < 0 且感化强盗次数 k > 0,金币数为 0(感化该强盗)。
  4. 最终结果

    • 机器人到达右下角 (m-1, n-1) 时,可能感化了 0、1 或 2 个强盗。最终答案为:

      max(dp[m-1][n-1][0], dp[m-1][n-1][1], dp[m-1][n-1][2])
      

3、代码实现

class Solution {
public:int maximumAmount(vector<vector<int>>& coins) {int m = coins.size();    // 网格的行数int n = coins[0].size(); // 网格的列数// 定义 DP 数组: dp[i][j][k] 表示到达 (i, j) 感化了 k 个强盗后的最大金币数vector<vector<vector<int>>> dp(m, vector<vector<int>>(n, vector<int>(3, INT_MIN)));// 初始化起点for (int k = 0; k <= 2; ++k) {dp[0][0][k] = (coins[0][0] < 0 && k > 0) ? 0 : coins[0][0];}// 动态规划填表for (int i = 0; i < m; ++i) {for (int j = 0; j < n; ++j) {// 遍历感化强盗的次数 kfor (int k = 0; k <= 2; ++k) {// 跳过起点if (i == 0 && j == 0) {continue;}int coinValue = coins[i][j]; // 当前单元格的金币值// 从上方到达当前单元格 (i, j)if (i > 0) {if (coinValue >= 0) {// 当前单元格是正值, 直接加金币dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j][k] + coinValue);} else {// 当前单元格是负值, 分两种情况讨论dp[i][j][k] =max(dp[i][j][k], dp[i - 1][j][k] + coinValue); // 不感化强盗if (k > 0) {dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j][k - 1]); // 感化强盗}}}// 从左侧到达当前单元格 (i, j)if (j > 0) {if (coinValue >= 0) {dp[i][j][k] = max(dp[i][j][k], dp[i][j - 1][k] + coinValue);} else {dp[i][j][k] = max(dp[i][j][k], dp[i][j - 1][k] + coinValue);if (k > 0) {dp[i][j][k] = max(dp[i][j][k], dp[i][j - 1][k - 1]);}}}}}}// 返回到达右下角时感化最多 2 个强盗的最大金币数return max({dp[m - 1][n - 1][0], dp[m - 1][n - 1][1], dp[m - 1][n - 1][2]});}
};

在这里插入图片描述

4、复杂度分析

时间复杂度

  • 三重循环:外层遍历网格的每个单元格,两层内循环遍历感化次数 k,总复杂度为 O ( m × n × 3 ) = O ( m × n ) O(m \times n \times 3) = O(m \times n) O(m×n×3)=O(m×n)

空间复杂度

  • 使用了一个三维数组 dp,大小为 O ( m × n × 3 ) O(m \times n \times 3) O(m×n×3)

Q3、图的最大边权的最小值

1、题目描述

给你两个整数 nthreshold ,同时给你一个 n 个节点的 有向 带权图,节点编号为 0n - 1 。这个图用 二维 整数数组 edges 表示,其中 edges[i] = [Ai, Bi, Wi] 表示节点 Ai 到节点 Bi 之间有一条边权为 Wi的有向边。

你需要从这个图中删除一些边(也可能 删除任何边),使得这个图满足以下条件:

  • 所有其他节点都可以到达节点 0 。
  • 图中剩余边的 最大 边权值尽可能小。
  • 每个节点都 至多threshold 条出去的边。

请你返回删除必要的边后,最大 边权的 最小值 为多少。如果无法满足所有的条件,请你返回 -1

2、解题思路

本题本质上是一个 图的最短路径问题,但有多个限制条件。我们可以通过以下步骤来思考并解决问题:

  1. 反向图构建
    我们需要从每个节点到达节点 0,所以我们构建图的 反向图。反向图中,原本从 AiBi 的边变为从 BiAi 的边。这样,我们只需要考虑从节点 0 到其他节点的路径即可。

  2. 最大边权最小化
    为了确保所有的节点都能到达节点 0,且最大边权最小,我们需要使用 最短路径算法。这里的最短路径的定义是:我们要求路径中的 最大边权最小,这和普通的最短路径问题有些不同。

    我们可以使用 Dijkstra 算法 来解决这个问题。Dijkstra 算法通常用于找到从起点到所有其他节点的最短路径,而在这个问题中,我们可以将路径的 “最短” 定义为 “最大边权最小”。

  3. 满足 threshold 条件
    限制每个节点至多有 threshold 条出去的边,意味着我们需要在考虑边的同时,保持每个节点的出度不超过 threshold。这个限制可以通过构建图时进行检查。

  4. 最终返回
    经过 Dijkstra 算法,我们能够找到从节点 0 到其他所有节点的最大边权。如果所有节点都能到达节点 0,则返回最大边权中的最小值;如果有节点无法到达节点 0,则返回 -1。

3、代码实现

class Solution {
public:int minMaxWeight(int n, vector<vector<int>>& edges, int threshold) {// 如果边小于 n-1, 直接返回 -1 (无法构成连通图)if (edges.size() < n - 1) {return -1;}// 构建反向图vector<vector<pair<int, int>>> g(n);// g[y] 包含 (x, w), 表示 x -> y 的边权为 wfor (const auto& edge : edges) {int x = edge[0], y = edge[1], w = edge[2];g[y].emplace_back(x, w);}// 初始化距离数组, 初始时所有节点的距离为正无穷const int INF = numeric_limits<int>::max();vector<int> dis(n, INF);dis[0] = 0; // 起点到自身的最大边权为 0// 最小堆, 存储 (最大边权, 节点编号)priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;pq.emplace(0, 0); // 起点while (!pq.empty()) {auto [d, x] = pq.top();pq.pop();// 如果当前距离大于记录的最小距离, 跳过if (d > dis[x]) {continue;}// 遍历当前节点的所有入边for (const auto& [y, w] : g[x]) {int new_d = max(d, w); // 更新最大边权// 如果找到更优的路径if (new_d < dis[y]) {dis[y] = new_d;pq.emplace(new_d, y);}}}// 找到所有节点到达 0 的最大边权值int ret = *max_element(dis.begin(), dis.end());return ret == INF ? -1 : ret; // 如果节点无法到达, 返回 -1, 否则返回答案}
};

在这里插入图片描述

4、复杂度分析

时间复杂度

  • 图的构建:O(E),其中 E 是边的数量。
  • Dijkstra 算法:O((E + V) log V),其中 E 是边数,V 是节点数。使用优先队列实现 Dijkstra,时间复杂度为 O((E + V) log V)

因此,整体时间复杂度为 O((E + V) log V)

空间复杂度

  • 使用了 O(V + E) 的空间来存储图和优先队列。

Q4、统计 K 次操作以内得到非递减子数组的数目

1、题目描述

给你一个长度为 n 的数组 nums 和一个整数 k

对于 nums 中的每一个子数组,你可以对它进行 至多 k 次操作。每次操作中,你可以将子数组中的任意一个元素增加 1 。

注意 ,每个子数组都是独立的,也就是说你对一个子数组的修改不会保留到另一个子数组中。

请你返回最多 k 次操作以内,有多少个子数组可以变成 非递减 的。

如果一个数组中的每一个元素都大于等于前一个元素(如果前一个元素存在),那么我们称这个数组是 非递减 的。

2、解题思路

我们需要通过合理的算法找到最多 k 次操作可以使得多少个子数组变为非递减的。对于每一个子数组,考虑以下步骤:

  1. 单调队列
    • 我们可以通过滑动窗口和单调队列来优化子数组的判断过程。
    • 在滑动窗口中,每次考虑将窗口的某一段变成非递减的子数组。
  2. 修正次数计算
    • 对于每个子数组,我们计算需要多少次操作使得它变为非递减。具体来说,如果 nums[i] > nums[i+1],我们需要进行 nums[i] - nums[i+1] 次操作才能使得 nums[i] 小于或等于 nums[i+1]
  3. 左边界和右边界的维护
    • 对于每个子数组,我们维护左右边界,确保在窗口内的操作次数不超过 k
    • 如果窗口内的操作次数超过 k,则我们调整窗口的左边界。
  4. 栈和单调队列的配合
    • 使用栈来维护每个元素的左边界和右边界,栈的作用是帮助我们快速找到某个元素的最近的一个较小元素。
    • 单调队列用于保持当前窗口内的元素的单调性,从而帮助我们高效地计算每个子数组的操作次数。

3、代码实现

class Solution {
public:long long countNonDecreasingSubarrays(vector<int>& nums, int k) {int n = nums.size();vector<int> left(n), right(n);vector<int> s = {-1}; // 栈, 初始化为 -1// 构造 left 和 right 数组for (int i = 0; i < n; ++i) {while (s.size() > 1 && nums[i] >= nums[s.back()]) {right[s.back()] = i; // 更新右边界s.pop_back();}left[i] = s.back(); // 栈顶是左侧 > nums[i] 的最近元素s.push_back(i);}for (int i : s) {if (i != -1) {// 栈中剩余元素的右边界为 nright[i] = n;}}// 记录每个 i 右侧有哪些位置的 left 是 ivector<vector<int>> g(n);for (int w = 0; w < n; ++w) {if (left[w] >= 0) {g[left[w]].push_back(w);}}// 滑动窗口 + 单调队列long long ret = 0;// 当前窗口内的修正次数int cnt = 0;// 窗口的左边界int l = 0;// 单调队列, 维护窗口最大值的下标deque<int> q;for (int r = 0; r < n; ++r) {int x = nums[r];// 计算窗口内最大值与当前值的差距if (!q.empty()) {cnt += max(nums[q.front()] - x, 0);}// 单调队列入队, 维持单调性while (!q.empty() && nums[q.back()] <= x) {q.pop_back();}q.push_back(r);// 调整窗口右边界, 直到满足修正次数的限制while (cnt > k) {int out = nums[l];for (int w : g[l]) {if (w > r) {break;}cnt -= (out - nums[w]) * (min(right[w] - 1, r) - w + 1);}++l;// 单调队列出队if (!q.empty() && q.front() < l) {q.pop_front();}}// 计算窗口内的子数组个数ret += r - l + 1;}return ret;}
};

在这里插入图片描述

4、复杂度分析

栈的处理:栈的操作复杂度是 O(n)

滑动窗口和单调队列:每次右边界 r 只会被访问一次,因此整体时间复杂度为 O(n)

总时间复杂度:由于主要的操作是 O(n),因此整体时间复杂度为 O(n)



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

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

相关文章

Harry技术添加存储(minio、aliyun oss)、短信sms(aliyun、模拟)、邮件发送等功能

Harry技术添加存储&#xff08;minio、aliyun oss&#xff09;、短信sms&#xff08;aliyun、模拟&#xff09;、邮件发送等功能 基于SpringBoot3Vue3前后端分离的Java快速开发框架 项目简介&#xff1a;基于 JDK 17、Spring Boot 3、Spring Security 6、JWT、Redis、Mybatis-P…

R数据分析:多分类问题预测模型的ROC做法及解释

有同学做了个多分类的预测模型,结局有三个类别,做的模型包括多分类逻辑回归、随机森林和决策树,多分类逻辑回归是用ROC曲线并报告AUC作为模型评估的,后面两种模型报告了混淆矩阵,审稿人就提出要统一模型评估指标。那么肯定是统一成ROC了,刚好借这个机会给大家讲讲ROC在多…

记一次学习skynet中的C/Lua接口编程解析protobuf过程

1.引言 最近在学习skynet过程中发现在网络收发数据的过程中数据都是裸奔&#xff0c;就想加入一种数据序列化方式&#xff0c;json、xml简单好用&#xff0c;但我就是不想用&#xff0c;于是就想到了protobuf&#xff0c;对于protobuf C/C的使用个人感觉有点重&#xff0c;正好…

SQLAlchemy

https://docs.sqlalchemy.org.cn/en/20/orm/quickstart.htmlhttps://docs.sqlalchemy.org.cn/en/20/orm/quickstart.html 声明模型 在这里&#xff0c;我们定义模块级构造&#xff0c;这些构造将构成我们从数据库中查询的结构。这种结构被称为 声明式映射&#xff0c;它同时定…

Trimble自动化激光监测支持历史遗产实现可持续发展【沪敖3D】

故事桥&#xff08;Story Bridge&#xff09;位于澳大利亚布里斯班&#xff0c;建造于1940年&#xff0c;全长777米&#xff0c;横跨布里斯班河&#xff0c;可载汽车、自行车和行人往返于布里斯班的北部和南部郊区。故事桥是澳大利亚最长的悬臂桥&#xff0c;是全世界两座手工建…

Playwright vs Selenium:全面对比分析

在现代软件开发中&#xff0c;自动化测试工具在保证应用质量和加快开发周期方面发挥着至关重要的作用。Selenium 作为自动化测试领域的老牌工具&#xff0c;长期以来被广泛使用。而近年来&#xff0c;Playwright 作为新兴工具迅速崛起&#xff0c;吸引了众多开发者的关注。那么…

Windows 程序设计3:宽窄字节的区别及重要性

文章目录 前言一、宽窄字节简介二、操作系统及VS编译器对宽窄字节的编码支持1. 操作系统2. 编译器 三、宽窄字符串的优缺点四、宽窄字节数据类型总结 前言 Windows 程序设计3&#xff1a;宽窄字节的区别及重要性。 一、宽窄字节简介 在C中&#xff0c;常用的字符串指针就是ch…

进阶——十六届蓝桥杯嵌入式熟练度练习(LED的全开,全闭,点亮指定灯,交替闪烁,PWM控制LED呼吸灯)

点亮灯的函数 void led_show(unsigned char upled) { HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOC,upled<<8,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RE…

力扣 最大子数组和

动态规划&#xff0c;前缀和&#xff0c;维护状态更新。 题目 从题可以看出&#xff0c;找的是最大和的连续子数组&#xff0c;即一个数组中的其中一个连续部分。从前往后遍历&#xff0c;每遍历到一个数可以尝试做叠加&#xff0c;注意是尝试&#xff0c;因为有可能会遇到一个…

Homestyler 和 Tripo AI 如何利用人工智能驱动的 3D 建模改变定制室内设计

让设计梦想照进现实 在Homestyler,我们致力于为每一个梦想设计师提供灵感的源泉,而非挫折。无论是初学者打造第一套公寓,或是专业设计师展示作品集,我们的直观工具都能让您轻松以惊人的3D形式呈现空间。 挑战:实现定制设计的新纪元 我们知道,将个人物品如传家宝椅子、…

算法练习4——一个六位数

这道题特别妙 大家仔细做一做 我这里采用的是动态规划来解这道题 结合题目要求找出数与数之间的规律 抽象出状态转移方程 题目描述 有一个六位数&#xff0c;其个位数字 7 &#xff0c;现将个位数字移至首位&#xff08;十万位&#xff09;&#xff0c;而其余各位数字顺序不…

client-go 的 QPS 和 Burst 限速

1. 什么是 QPS 和 Burst &#xff1f; 在 kubernetes client-go 中&#xff0c;QPS 和 Burst 是用于控制客户端与 Kubernetes API 交互速率的两个关键参数&#xff1a; QPS (Queries Per Second) 定义&#xff1a;表示每秒允许发送的请求数量&#xff0c;即限速器的平滑速率…

太原理工大学软件设计与体系结构 --javaEE

这个是简答题的内容 选择题的一些老师会给你们题库&#xff0c;一些注意的点我会做出文档在这个网址 项目目录预览 - TYUT复习资料:复习资料 - GitCode 希望大家可以给我一些打赏 什么是Spring的IOC和DI IOC 是一种设计思想&#xff0c;它将对象的创建和对象之间的依赖关系…

深度学习知识点:LSTM

文章目录 1.应用现状2.发展历史3.基本结构4.LSTM和RNN的差异 1.应用现状 长短期记忆神经网络&#xff08;LSTM&#xff09;是一种特殊的循环神经网络(RNN)。原始的RNN在训练中&#xff0c;随着训练时间的加长以及网络层数的增多&#xff0c;很容易出现梯度爆炸或者梯度消失的问…

mmdet

一&#xff0c;configs/_base_ 1.default_runtime.py 2.schedule_1x.py 二&#xff0c;mmdet 1.datasets/coco.py/CocoDataset METAINFO {classes:(milk, red, spring, fanta, sprite, pepsi, king, ice, cola, scream ),# palette is a list of color tuples, which is us…

ElasticSearch 认识和安装ES

文章目录 一、为什么学ElasticSearch?1.ElasticSearch 简介2.ElasticSearch 与传统数据库的对比3.ElasticSearch 应用场景4.ElasticSearch 技术特点5.ElasticSearch 市场表现6.ElasticSearch 的发展 二、认识和安装ES1.认识 Elasticsearch&#xff08;简称 ES&#xff09;2.El…

第34天:安全开发-JavaEE应用反射机制攻击链类对象成员变量方法构造方法

时间轴&#xff1a; Java反射相关类图解&#xff1a; 反射&#xff1a; 1、什么是 Java 反射 参考&#xff1a; https://xz.aliyun.com/t/9117 Java 提供了一套反射 API &#xff0c;该 API 由 Class 类与 java.lang.reflect 类库组成。 该类库包含了 Field 、 Me…

汽车基础软件AutoSAR自学攻略(三)-AutoSAR CP分层架构(2)

汽车基础软件AutoSAR自学攻略(三)-AutoSAR CP分层架构(2) 下面我们继续来介绍AutoSAR CP分层架构&#xff0c;下面的文字和图来自AutoSAR官网目前最新的标准R24-11的分层架构手册。该手册详细讲解了AutoSAR分层架构的设计&#xff0c;下面让我们来一起学习一下。 Introductio…

css面试常考布局(圣杯布局、双飞翼布局、三栏布局、两栏布局、三角形)

两栏布局 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head> &…

网络攻击行为可视化分析系统【数据分析 + 可视化】

一、系统背景 随着信息技术的快速发展&#xff0c;网络已成为现代社会不可或缺的一部分。然而&#xff0c;与此同时&#xff0c;网络攻击手段也日益多样化和复杂化&#xff0c;给企业和个人的信息安全带来了极大的威胁。传统的网络攻击分析方法往往依赖于人工分析和处理大量的…