【Java算法】前缀和 下

  🔥个人主页: 中草药

🔥专栏:【算法工作坊】算法实战揭秘


一.连续数组

题目链接:525.连续数组

代码

 public int findMaxLength(int[] nums) {HashMap<Integer,Integer> map=new HashMap<>();map.put(0,-1);int sum=0,ret=0;for(int i=0;i<nums.length;i++){sum+=(nums[i]==0?-1:1);if(map.containsKey(sum)){ret=Math.max(ret,i-map.get(sum));}else{map.put(sum,i);}}return ret;}

算法原理

这段代码实现了一个寻找数组中具有相等数量的0和1的最长子数组长度的算法。具体来说,它使用了前缀和(prefix sum)的概念以及哈希映射(HashMap)来优化查找过程。

  1. 初始化哈希映射

    • 创建一个HashMap,用来存储前缀和与对应的数组索引。
    • 初始时,将前缀和为0的情况标记在索引-1处,这是为了处理从数组开始位置就有相等数量的0和1的情况。
  2. 计算前缀和

    • 遍历数组中的每一个元素nums[i]
    • 如果nums[i]是0,则将其视为-1,如果是1,则保持为1。这样,我们可以用加法来累积0和1的差值。
    • sum变量用于跟踪当前遍历到的位置为止的累积差值。
  3. 检查相等数量的0和1

    • 每次更新sum后,我们检查sum是否已经存在于HashMap中。
    • 如果存在,这意味着从前一次出现相同sum的点到当前点之间,0和1的数量是相等的(因为累积的差值没有改变)。
    • 我们可以通过当前索引i减去先前sum出现的索引来计算这个子数组的长度,并更新最长子数组的记录。
  4. 更新哈希映射

    • 如果sum不在HashMap中,说明我们首次遇到这个累积差值。我们将sum及其对应的索引i添加到HashMap中。
  5. 返回结果

    • 在遍历完整个数组后,返回最长子数组的长度。

这种方法的时间复杂度为O(n),因为我们只遍历数组一次,并且对每个元素执行常数时间的操作。空间复杂度也是O(n),最坏情况下需要存储n个前缀和值。

举例 

测试用例  nums = [0,1,0]
  1. 初始化阶段:

    • 哈希映射map被创建并初始化,其中map.put(0, -1),表示前缀和为0的初始位置在-1,这是为了处理从数组开始就有相等数量的0和1的情况。
  2. 开始遍历数组:

    • 对于nums[0]0,由于nums[i] == 0,因此sum增加-1,此时sum = -1
      • map中不存在键-1,所以将sum = -1和其对应的索引i = 0放入map中。
    • map现在包含{0: -1, -1: 0}
  3. 继续遍历:

    • 对于nums[1]1sum增加1(因为nums[i] == 1),此时sum = 0
      • map中存在键0,这表明从map.get(0) = -1(即数组的起始点之前)到当前索引i = 1之间的子数组[0, 1]有相等数量的0和1。
      • 计算子数组长度i - map.get(sum) = 1 - (-1) = 2,更新ret为最大值,即ret = 2
    • 此时map包含{0: -1, -1: 0, 0: 1},但是我们不需要保留旧的0键值对,通常这个实现中不会更新键值对,而是会在下一次遇到相同的sum时计算新的子数组长度。
  4. 最后一个元素:

    • 对于nums[2]0,再次sum增加-1,此时sum = -1
      • map中存在键-1,这表明从map.get(-1) = 0到当前索引i = 2之间的子数组[1, 0]有相等数量的0和1。
      • 计算子数组长度i - map.get(sum) = 2 - 0 = 2,但ret已经是2,所以ret保持不变。
  5. 返回结果:

    • 遍历结束后,ret的值为2,表示最长子数组的长度是2。

因此,对于nums = [0, 1, 0],这段代码会正确地返回最长子数组长度为2,即子数组[0, 1][1, 0]。值得注意的是,尽管最后的结果是正确的,但根据题目要求和具体实现细节,可能有多个满足条件的子数组,而这段代码仅返回长度信息,不提供具体的子数组元素。

二.和为k的子数组

题目链接:560.和为k的子数组

代码

public int subarraySum(int[] nums, int k) {HashMap<Integer,Integer> map=new HashMap<>();map.put(0,1);int ret=0,sum=0;for(int i=0;i<nums.length;i++){sum+=nums[i];ret+=map.getOrDefault(sum-k,0);map.put(sum,map.getOrDefault(sum,0)+1);}return ret;}

算法原理

这段代码实现了一个算法,用于找到数组nums中所有和等于给定值k的连续子数组的个数。该算法的核心思想同样基于前缀和和哈希映射,但这里的目标是在遍历过程中查找是否有任何前缀和能够与当前前缀和形成差值为k的配对。

以下是算法的详细步骤:

  1. 初始化哈希映射

    • 创建一个HashMap,用来存储前缀和与对应的出现次数。
    • 初始时,将前缀和为0的情况标记出现次数为1。这是为了处理从数组开始位置就有和等于k的子数组的情况。
  2. 初始化变量

    • ret用于累计满足条件的子数组的个数。
    • sum用于跟踪当前遍历到的位置为止的累积和。
  3. 遍历数组

    • 遍历数组中的每一个元素nums[i]
    • 更新sum,使其反映当前位置为止的累积和。
  4. 查找匹配的前缀和

    • 使用getOrDefault方法查询map中是否存在sum - k的前缀和。
    • 如果存在,意味着从某个位置到当前位置的累积和正好为kgetOrDefault返回的值是这个前缀和出现的次数,将其累加到ret中,代表找到了这么多满足条件的子数组。
  5. 更新哈希映射

    • 将当前的sum及其对应的出现次数更新到map中。如果sum已经在map中,那么它的计数器加1;否则,设置为1。
  6. 返回结果

    • 在遍历完整个数组后,ret包含了所有满足条件的子数组的个数,直接返回即可。

这种方法的时间复杂度同样是O(n),因为我们只遍历数组一次,并且每次操作都是常数时间的。空间复杂度为O(n),因为在最坏的情况下,哈希映射可能需要存储n个不同的前缀和。这种算法利用了哈希映射快速查找和插入的特点,从而实现了高效的解决方案。

举例

测试用例 nums = [1,2,3], k = 3
  1. 初始化阶段:

    • 创建哈希映射map并初始化,其中map.put(0, 1),表示前缀和为0的出现次数为1。
  2. 遍历数组:

    • 对于nums[0]1

      • 当前累积和sum更新为1
      • 查询map中是否存在sum - k = 1 - 3 = -2,显然不存在,因此ret不改变。
      • 更新mapmap.put(sum, map.getOrDefault(sum, 0) + 1),即map.put(1, 1),因为1的前缀和第一次出现。
    • 对于nums[1]2

      • 当前累积和sum更新为3
      • 查询map中是否存在sum - k = 3 - 3 = 0,存在并且出现次数为1,因此ret增加1,现在ret = 1
      • 更新mapmap.put(3, map.getOrDefault(3, 0) + 1),即map.put(3, 1),因为3的前缀和第一次出现。
    • 对于nums[2]3

      • 当前累积和sum更新为6
      • 查询map中是否存在sum - k = 6 - 3 = 3,存在并且出现次数为1,因此ret再增加1,现在ret = 2
      • 更新mapmap.put(6, map.getOrDefault(6, 0) + 1),即map.put(6, 1),因为6的前缀和第一次出现。
  3. 返回结果:

    • 遍历结束后,ret的值为2,表示有2个连续子数组的和等于k

通过上面的分析,我们发现确实有两个子数组的和等于k = 3,分别是[1, 2][3]。因此,这段代码对于测试用例nums = [1, 2, 3]k = 3,会正确返回2作为结果。

三.和可被k整除的子数组

题目链接:974.和可被k整除的子数组

代码

public int subarraysDivByK(int[] nums, int k) {HashMap<Integer,Integer> map=new HashMap<>();map.put(0,1);int ret=0,sum=0;for(int i=0;i<nums.length;i++){sum+=nums[i];int r=(sum%k+k)%k;//对负数的处理//根据,同余定理,(sum-x)%k==0,sum%k==0,x%k==0ret+=map.getOrDefault(r,0);map.put(r,map.getOrDefault(r,0)+1);}return ret;}

算法原理

        实现了一个算法,用于寻找数组nums中所有和能被整数k整除的连续子数组的个数。这里的算法原理与之前的略有不同,主要是针对模运算的特性进行优化,特别是处理负数模运算的情况。

        算法的关键点在于使用模运算的性质来简化问题,并利用哈希映射来存储和查找特定的模结果。以下是算法的详细步骤:

  1. 初始化哈希映射

    • 创建一个HashMap,用来存储模结果与对应的出现次数。
    • 初始时,将模结果为0的出现次数标记为1。这是因为如果累积和本身就能被k整除,那么从数组的起始位置到当前位置的子数组就满足条件。
  2. 遍历数组

    • 遍历数组中的每一个元素nums[i]
    • 更新sum,使其反映当前位置为止的累积和。
  3. 处理模运算

    • 为了确保模运算结果始终为正,使用(sum % k + k) % k的技巧。这是因为sum % k可能得到一个负数(当sum % k < 0时),而我们需要确保r始终在0k-1之间。这个技巧保证了即使sum % k是负数,r也能正确地映射到0k-1的范围内。
  4. 查找匹配的模结果

    • 使用getOrDefault方法查询map中是否存在r的模结果。
    • 如果存在,意味着从某个位置到当前位置的累积和模k的结果为r,且已有其他子数组也得到同样的模结果。getOrDefault返回的值是这个模结果出现的次数,将其累加到ret中,代表找到了这么多满足条件的子数组。
  5. 更新哈希映射

    • 将当前的模结果r及其对应的出现次数更新到map中。如果r已经在map中,那么它的计数器加1;否则,设置为1。
  6. 返回结果

    • 在遍历完整个数组后,ret包含了所有满足条件的子数组的个数,直接返回即可。

这种方法的时间复杂度仍然是O(n),因为我们只遍历数组一次,并且每次操作都是常数时间的。空间复杂度为O(k),因为在最坏的情况下,哈希映射可能需要存储k个不同的模结果。通过这种方式,算法有效地利用了模运算的性质和哈希映射的快速查找能力,实现了高效解决方案。

举例

测试用例 nums = [4,5,0,-2,-3,1], k = 5
  1. 初始化阶段:

    • 创建哈希映射map并初始化,其中map.put(0, 1),表示模结果为0的出现次数为1。
  2. 遍历数组:

    • 对于nums[0]4

      • 当前累积和sum更新为4
      • 计算模结果r = (sum % k + k) % k = (4 % 5 + 5) % 5 = 4
      • 查询map中是否存在r = 4,显然不存在,因此ret不改变。
      • 更新mapmap.put(4, map.getOrDefault(4, 0) + 1),即map.put(4, 1),因为4的模结果第一次出现。
    • 对于nums[1]5

      • 当前累积和sum更新为9
      • 计算模结果r = (9 % 5 + 5) % 5 = 4
      • 查询map中是否存在r = 4,存在并且出现次数为1,因此ret增加1,现在ret = 1
      • 更新mapmap.put(4, map.getOrDefault(4, 0) + 1),即map.put(4, 2),因为4的模结果第二次出现。
    • 对于nums[2]0

      • 当前累积和sum更新为9
      • 计算模结果r = (9 % 5 + 5) % 5 = 4
      • 查询map中是否存在r = 4,存在并且出现次数为2,因此ret再增加2,现在ret = 3
      • 更新mapmap.put(4, map.getOrDefault(4, 0) + 1),即map.put(4, 3),因为4的模结果第三次出现。
    • 对于nums[3]-2

      • 当前累积和sum更新为7
      • 计算模结果r = (7 % 5 + 5) % 5 = 2
      • 查询map中是否存在r = 2,显然不存在,因此ret不改变。
      • 更新mapmap.put(2, map.getOrDefault(2, 0) + 1),即map.put(2, 1),因为2的模结果第一次出现。
    • 对于nums[4]-3

      • 当前累积和sum更新为4
      • 计算模结果r = (4 % 5 + 5) % 5 = 4
      • 查询map中是否存在r = 4,存在并且出现次数为3,因此ret再增加3,现在ret = 6
      • 更新mapmap.put(4, map.getOrDefault(4, 0) + 1),即map.put(4, 4),因为4的模结果第四次出现。
    • 对于nums[5]1

      • 当前累积和sum更新为5
      • 计算模结果r = (5 % 5 + 5) % 5 = 0
      • 查询map中是否存在r = 0,存在并且出现次数为1,因此ret再增加1,现在ret = 7
      • 更新mapmap.put(0, map.getOrDefault(0, 0) + 1),即map.put(0, 2),因为0的模结果第二次出现。
  3. 返回结果:

    • 遍历结束后,ret的值为7,表示有7个连续子数组的和能被k = 5整除。

通过上面的分析,我们可以看到,确实有7个子数组的和能被5整除,例如[4][4, 5][4, 5, 0][5][5, 0][5, 0, -2, -3]、和[1]。因此,这段代码对于测试用例nums = [4, 5, 0, -2, -3, 1]k = 5,会正确返回7作为结果。

四.矩阵区域和

题目链接:1314.矩阵区域和

代码

 public int[][] matrixBlockSum(int[][] mat, int k) {int m=mat.length,n=mat[0].length;int[][] dp=new int[m+1][n+1];//预处理前缀和矩阵for(int i=1;i<dp.length;i++){for(int j=1;j<dp[0].length;j++){dp[i][j]=dp[i-1][j]+dp[i][j-1]+mat[i-1][j-1]-dp[i-1][j-1];//由于边界情况的处理,故加上的mat[i][j]变为mat[i-1][j-1]}}//求解int[][] ret=new int[m][n];for(int i=0;i<ret.length;i++){for(int j=0;j<ret[0].length;j++){int x1=Math.max(0,i-k)+1;int y1=Math.max(0,j-k)+1;int x2=Math.min(m-1,i+k)+1;int y2=Math.min(n-1,j+k)+1;ret[i][j]=dp[x2][y2]-dp[x1-1][y2]-dp[x2][y1-1]+dp[x1-1][y1-1];}}return ret;}

算法原理

这段代码实现了一个算法,用于计算二维矩阵mat中每个元素为中心、边长为2*k+1的正方形区域内的元素之和,并将这些和组成一个新的矩阵ret返回。这里采用的是前缀和矩阵的方法,它是一种高效的空间换时间的策略,特别适用于解决二维范围查询问题。

算法的原理可以分为以下几步:

  1. 构建前缀和矩阵

    • 首先创建一个比原矩阵mat大一圈的二维数组dp,用于存储前缀和。额外的一圈是为了简化边界条件的处理。
    • 通过两重循环遍历dp矩阵的内部(从dp[1][1]开始),计算前缀和。
    • 前缀和的计算公式为:dp[i][j] = dp[i-1][j] + dp[i][j-1] + mat[i-1][j-1] - dp[i-1][j-1]
    • 这个公式实际上计算了以(i-1, j-1)为右下角的矩形区域内的元素之和。注意,由于dp矩阵的大小比mat大一圈,所以在公式中使用mat[i-1][j-1]
  2. 计算查询结果矩阵

    • 创建一个与mat大小相同的矩阵ret,用于存储最终结果。
    • 再次通过两重循环遍历mat矩阵,对于每个位置(i, j)
      • 确定查询的四个边界:左上角(x1, y1)和右下角(x2, y2),考虑到边界条件,确保它们都在矩阵的有效范围内。
      • 使用前缀和矩阵dp计算以(i, j)为中心的2*k+1大小的正方形区域内元素之和。公式为:ret[i][j] = dp[x2][y2] - dp[x1-1][y2] - dp[x2][y1-1] + dp[x1-1][y1-1]
      • 这个公式实际上是利用前缀和矩阵的性质,从大矩形中减去三个不需要的小矩形区域,得到目标区域的元素之和。
  3. 返回结果矩阵

    • 完成所有位置的计算后,返回结果矩阵ret

这种方法的时间复杂度主要由两次遍历构成,分别是构建前缀和矩阵和计算查询结果,均为O(mn),其中m和n分别是矩阵的行数和列数。空间复杂度为O(mn),用于存储前缀和矩阵和结果矩阵。通过前缀和矩阵的使用,避免了对每个查询重复计算区域和,从而大大提高了效率。


🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀

以上,就是本期的全部内容啦,若有错误疏忽希望各位大佬及时指出💐

  制作不易,希望能对各位提供微小的帮助,可否留下你免费的赞呢🌸

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【系统架构设计师】十三、软件可靠性(基本概念|软件可靠性建模)

目录 一、基本概念 1.1 定义 1.2 软件可靠性的定量描述 1.3 可靠性测试的意义 1.4 广义的软件可靠性测试和狭义的软件可靠性测试 二、软件可靠性建模 2.1 可靠性模型的组成 2.2 可靠性模型的共同假设 2.3 可靠性模型的重要特性 2.4 可靠性建模方法 往期推荐 历年真…

SD-WAN组网搭建5G备份方案实现方式

SD-WAN&#xff08;Software-Defined Wide Area Network&#xff0c;软件定义广域网&#xff09;结合5G作为备份链路是现代企业网络弹性策略的一部分&#xff0c;尤其是在需要高可用性和快速故障切换的场景下。以下是实现SD-WAN组网并集成5G备份方案的一般步骤&#xff1a; 1. …

‍我想我大抵是疯了,我喜欢上了写单元测试

前言 大家好我是聪。相信有不少的小伙伴喜欢写代码&#xff0c;但是对于单元测试这些反而觉得多此一举&#xff0c;想着我都在接口文档测过了&#xff01;还要写什么单元测试&#xff01;写不了一点&#xff01;&#xff01; 由于本人也是一个小小程序猿&#x1f649;&#xf…

Python | 分享8个Excel自动化脚本,一定有你用得上的!

本文将介绍8个常用的Python脚本&#xff0c;帮助你轻松应对Excel的日常操作。那话不多说&#xff0c;开始吧&#xff01; 1. 安装所需的Python库 在开始之前&#xff0c;我们需要安装一些Python库来操作Excel文件。以下是需要安装的库&#xff1a; pandas&#xff1a;用于数据…

Java 实验七:集合的使用

一、实验目的 1、理解Java集合框架的特点、接口与类之间的关系&#xff1b; 2、掌握Java集合框架的List接口&#xff0c;以及List接口的重要实现类LinkedList、ArrayList&#xff1b; 3、掌握Java集合框架的Set、SortedSet接口&#xff0c;以及重要实现类HashSet 与 TreeSet…

活动回顾 | AutoMQ 联合 GreptimeDB 共同探讨新能源汽车数据基础设施

7 月 13 日&#xff0c;AutoMQ 携手 GreptimeDB“新能源汽车数据基础设施” 主题 meetup 在上海圆满落幕。本次论坛多角度探讨如何通过创新的数据管理和存储架构&#xff0c;提升汽车系统的性能、安全性和可靠性&#xff0c;从而驱动行业的持续发展和创新&#xff0c;涵盖 Auto…

C#字符串基本操作

1、代码 //1、创建字符串&#xff08;获取长度&#xff09;string str "Hello, World!";Console.WriteLine($"string:{str},length:{str.Length}");//2、字符串连接string str1 "Hello, ";string str2 "World!";Console.WriteLine…

简易ELK搭建

ELK搭建 1. elasticsearch1.1 下载1.2 ES配置1.3 启动ES1.4 开启权限认证1.5 IK分词器配置&#xff08;非必须&#xff09; 2. kibana2.1 下载2.2 配置2.3 启动kibana 3. logstash3.1 下载3.2 配置3.3 启动logstash 4. springboot推送数据 ELK包括elasticsearch、logstash、kib…

【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析

初阶数据结构相关知识点可以通过点击以下链接进行学习一起加油&#xff01;时间与空间复杂度的深度剖析深入解析顺序表:探索底层逻辑深入解析单链表:探索底层逻辑深入解析带头双向循环链表:探索底层逻辑深入解析栈:探索底层逻辑深入解析队列:探索底层逻辑深入解析循环队列:探索…

25.dom创建、获取、插入、替换、删除、克隆节点

dom节点 -构成页面的每个组成部分&#xff08;标签 属性 文字 注释&#xff09; 节点(所有的文本内容 包括换行和空格) 元素节点(页面上的每个标签) 属性节点(标签上的属性) 注释节点(所有的注释内容包括注释内的空格换行) 创建节点 创建文本节点&#xff1a; var 变量名docume…

Sui基金会公布第一批RFP资助获得者名单

Sui资助计划已经从RFP申请者中选出了第一批受资助名单&#xff0c;这一举措标志着我们在促进Sui生态创新和增长方面迈出的重要一步。RFP计划旨在解决生态内的特定需求&#xff0c;为与我们战略目标一致的项目提供有针对性的支持。 为非技术者打造兼容Kiosk的启动平台 现存问题…

更新:彩虹云商城系统 自助下单免授权无后门源码(修复完整版)

源码简介&#xff1a; 最新更新彩虹云商城系统&#xff0c;自助下单免授权无后门源码&#xff08;修复完整版&#xff09; 自助下单彩虹云商城系统。这玩意儿不简单&#xff0c;它是高效稳定的电商平台&#xff01;免授权源码版本&#xff0c;灵活方便。源码是用PHP语言写的。…

[CP_AUTOSAR]_分层软件架构_接口之内存模块的交互介绍

目录 1、Memory service modules 特征及差异2、Memory 如何通信交互2.1、Memory通信架构2.2、大块的NV数据管理 3、Memory 软件接口4、内存抽象接口的实现3.1、情况1&#xff1a;只使用了一种NV设备类型3.2、情况2&#xff1a;使用了2种或更多的NV设备 4、结论 在前面 关于接口…

2. KNN分类算法与鸢尾花分类任务

鸢尾花分类任务 1. 鸢尾花分类步骤1.1 分析问题&#xff0c;搞定输入和输出1.2 每个类别各采集50朵花1.3 选择一种算法&#xff0c;完成输入到输出的映射1.4 第四步&#xff1a;部署&#xff0c;集成 2. KNN算法原理2.1 基本概念2.2 核心理念2.3 训练2.4 推理流程 3. 使用 skle…

路由数据获取及封装方法

数据库设计 自联表 定义tree字段 public class LabelValue{public int label { get; set; }public string? value { get; set; }public List<LabelValue> children { get; set; }}获取路由方法 public Response<object> getMenuList() {Response<object>…

spark 事件总线listenerBus

事件总线基本流程 图片来源&#xff1a;https://blog.csdn.net/sinat_26781639/article/details/105012302 LiveListenerBus创建 在sparkContext初始化中创建LiveListenerBus对象。 主要变量有两个 queues&#xff1a;事件队列&#xff0c;里面存放四个队列&#xff0c;每…

零基础学习Python(三)

1. 多重继承 一个子类可以继承多个父类&#xff0c;这与一些编程语言的规则不通。 如果多个父类中有同名的变量和方法&#xff0c;子类访问的顺序是按照继承时小括号里书写的顺序进行访问的。 可以用issubclass(B, A)方法判断B是否为A的子类。 2. 绑定 类中的方法通过参数s…

Unity 导入MRTK,使用URP 升级材质,MRTK的材质还是洋红色

控制台显示信息 ToggleBackground material was not upgraded. There’s no upgrader to convert Mixed Reality Toolkit/Standard shader to selected pipeline UnityEditor.Rendering.Universal.UniversalRenderPipelineMaterialUpgrader:UpgradeProjectMaterials() (at 点击…

Windows 电脑部署 ollama3 并安装模型

Windows 电脑部署 ollama3 并安装模型 部署中为了尽可能减少对本地环境的污染&#xff0c;使用 Docker 安装&#xff01; github: https://github.com/ollama/ollama 准备部署文件 version: 3.8services:ollama:volumes:- ./models:/root/.ollama # 将本地文件夹挂载到容器中…

window11 部署llama.cpp并运行Qwen2-0.5B-Instruct-GGUF

吾名爱妃&#xff0c;性好静亦好动。好编程&#xff0c;常沉浸于代码之世界&#xff0c;思维纵横&#xff0c;力求逻辑之严密&#xff0c;算法之精妙。亦爱篮球&#xff0c;驰骋球场&#xff0c;尽享挥洒汗水之乐。且喜跑步&#xff0c;尤钟马拉松&#xff0c;长途奔袭&#xf…