LeetCode 每日一题笔记 日期:2026.05.07 题目:3660. 找到所有可以到达的最大值

LeetCode 每日一题笔记

0. 前言

  • 日期:2026.05.07
  • 题目:3660. 找到所有可以到达的最大值
  • 难度:中等
  • 标签:数组、贪心、前缀最值、递归

1. 题目理解

问题描述

给定一个整数数组 nums。对于数组中的每一个位置 i,你可以按照下面的规则跳跃任意次数:

  • 向右跳:只能跳到比当前数的数
  • 向左跳:只能跳到比当前数的数

请你返回一个数组 ans,其中 ans[i] 表示从位置 i 出发,能够到达的最大数值

示例

输入:nums = [2,1,3]

输出:[2,2,3]

2. 解题思路

核心观察

  1. 每个位置能到达的最大值,取决于左边的最大值是否能"打通"到更全局的最大值。
  2. 一旦左边出现比右侧最小值更大的数,就可以到达全局最大值
  3. 可以用前缀最大值快速记录每个位置左侧的最大值及其下标。
  4. 递归思路:从右向左分割区间,用最大值把数组分成两段,分别赋值答案。

算法步骤

原版递归思路

  1. 预处理前缀最大值数组,记录每个位置的最大值及其下标。
  2. 从右往左递归处理:
    • 找到当前区间的最大值位置
    • 如果该最大值 > 右侧最小值,说明能到达全局最大值
    • 给区间内所有位置赋值当前最大值
    • 继续递归处理左半区间

优化版思路

  1. 先求一遍前缀最大值。
  2. 从右往左遍历,维护当前最小值 mn 和当前可达最大值 mx
  3. 如果前缀最大值 > 当前最小值,说明能到达全局最大值,直接赋值。
  4. 否则更新最大值和最小值。

3. 代码实现

原版代码(递归 + 前缀最值)

java 复制代码
package lc3660;

class Solution {
    public void erFen(int[] nums, int right, int[] res, int[][] prevmax, int min, int max) {
        if (right <= 0) {
            return;
        }
        int nowMax = prevmax[right - 1][0];
        int nowMaxLoc = prevmax[right - 1][1];
        if (nowMax > min) {
            nowMax = max;
        }
        for (int i = nowMaxLoc; i < right; i++) {
            if (nums[i] < min) {
                min = nums[i];
            }
            res[i] = nowMax;
        }
        right = nowMaxLoc;
        erFen(nums, right, res, prevmax, min, max);
    }

    public int[] maxValue(int[] nums) {
        int[] res = new int[nums.length];
        int[][] prevMax = new int[nums.length][2];
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] > max) {
                max = nums[i];
                prevMax[i][0] = max;
                prevMax[i][1] = i;
            } else {
                prevMax[i][0] = prevMax[i - 1][0];
                prevMax[i][1] = prevMax[i - 1][1];
            }
        }
        erFen(nums, nums.length, res, prevMax, Integer.MAX_VALUE, prevMax[nums.length - 1][0]);
        return res;
    }
}

优化版代码

java 复制代码
class Solution {
public int[] maxValue(int[] nums) {
int n = nums.length;
int[] sum = new int[n];
sum[0] = nums[0];
for(int i = 1; i < n; i++){
sum[i] = Math.max(sum[i - 1], nums[i]);
}
int mn = nums[n - 1];
int mx = sum[n - 1];
for(int j = n - 1; j >= 0; j--){
if(sum[j] > mn){
sum[j] = mx;
}
else{
mx = sum[j];
}
mn = Math.min(mn, nums[j]);
}
return sum;
}
}

4. 代码优化说明

  • 原版使用递归 + 前缀最大值数组,思路直观,通过分段赋值得到答案。
  • 优化版使用一次前缀最大值 + 一次反向遍历,去掉递归,时间、空间更优。
  • 优化版不再需要二维数组,仅用一个数组即可完成计算,代码更简洁。

5. 复杂度分析

原版代码

  • 时间复杂度:O(n)O(n)O(n) ~ O(n2)O(n^2)O(n2) (取决于递归分割次数)
  • 空间复杂度:O(n)O(n)O(n) (前缀数组 + 递归栈)

优化版代码

  • 时间复杂度:O(n)O(n)O(n)
  • 空间复杂度:O(n)O(n)O(n) (仅使用结果数组)

6. 总结

  • 本题核心是判断每个位置能否到达全局最大值
  • 关键依据:如果左边有更大的数,且能"打通"到右侧,就能取全局最大。
  • 从右往左遍历 + 维护最小/最大值,是本题最优思路。
  • 递归版本易于理解,迭代优化版本效率更高。
相关推荐
经济元宇宙2 小时前
哪款工业仿真软件上手简单?企业常用款推荐
人工智能·算法
Hesionberger2 小时前
LeetCode79:单词搜索DFS回溯详解
java·开发语言·c++·python·算法·leetcode·c#
wangcheng3033 小时前
智算集群:你身边的智能算力新形态
笔记
纪伊路上盛名在3 小时前
聊一聊关于gene的富集分析
算法·数据分析·统计分析·计算生物·gene
米粒13 小时前
力扣算法刷题 Day 62 最短路算法
算法·leetcode·职场和发展
时空自由民.4 小时前
三个按键的,短按1S,长按3S,单击,双击,三击的检测程序
大数据·数据库·计算机网络·算法
dog2504 小时前
圆锥曲线命题的定义和证明
网络·算法·php
IT猿手4 小时前
光伏模型参数估计:山羊优化算法(Goat Optimization Algorithm, GOA)求解光伏模型参数辨识问题,免费提供完整MATLAB代码链接
开发语言·算法·matlab·智能优化算法·光伏模型参数估计·光伏模型参数辨识·最新群智能算法
kels88994 小时前
2026 年黄金实时价格数据 API 接口实测推荐
开发语言·笔记·python·金融·区块链