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

丛台专业做网站在线建站平台

丛台专业做网站,在线建站平台,后端工资一般比前端高吗,学校网站建设主要成绩题目描述 给定一个长度为 n 的下标从 0 开始的整数数组 nums。初始位置为下标 0。当 i < j 时&#xff0c;你可以从下标 i 跳转到下标 j: 对于在 i < k < j 范围内的所有下标 k 有 nums[i] < nums[j] 和 nums[k] < nums[i] , 或者对于在 i < k < j 范围…

题目描述

给定一个长度为 n 的下标从 0 开始的整数数组 nums。初始位置为下标 0。当 i < j 时,你可以从下标 i 跳转到下标 j:

  • 对于在 i < k < j 范围内的所有下标 k 有 nums[i] <= nums[j] 和 nums[k] < nums[i] , 或者
  • 对于在 i < k < j 范围内的所有下标 k 有 nums[i] > nums[j] 和 nums[k] >= nums[i] 。

你还得到了一个长度为 n 的整数数组 costs,其中 costs[i] 表示跳转下标 i 的代价。

返回跳转到下标 n - 1 的最小代价。

示例 1:

输入: nums = [3,2,4,4,1], costs = [3,7,6,4,2]
输出: 8
解释: 从下标 0 开始。
- 以 costs[2]= 6 的代价跳转到下标 2。
- 以 costs[4]= 2 的代价跳转到下标 4。
总代价是 8。可以证明,8 是所需的最小代价。
另外两个可能的路径是:下标 0 -> 1 -> 4 和下标 0 -> 2 -> 3 -> 4。
它们的总代价分别为9和12。

示例 2:

输入: nums = [0,1,2], costs = [1,1,1]
输出: 2
解释: 从下标 0 开始。
- 以 costs[1] = 1 的代价跳转到下标 1。
- 以 costs[2] = 1 的代价跳转到下标 2。
总代价是 2。注意您不能直接从下标 0 跳转到下标 2,因为 nums[0] <= nums[1]。

解释:

  • n == nums.length == costs.length
  • 1 <= n <= 10^5
  • 0 <= nums[i], costs[i] <= 10^5

问题分析

这道题是跳跃游戏系列中的一道具有挑战性的题目。关键在于理解跳跃条件:

跳跃条件解析:

  • 条件一: nums[i] <= nums[j] 且中间所有 nums[k] < nums[i]

    • 含义:从位置i跳到右侧第一个 ≥ nums[i] 的位置

    • 对应:单调递减栈(维护一个从栈底到栈顶递减的序列)

  • 条件二: nums[i] > nums[j] 且中间所有 nums[k] >= nums[i]

    • 含义:从位置i跳到右侧第一个 < nums[i] 的位置

    • 对应:单调递增栈(维护一个从栈底到栈顶递增的序列)

这两个条件实际上是互补的,可以用单调栈来高效处理。


解题思路

单调栈 + 动态规划

核心思想:

  1. 使用两个单调栈分别处理两种跳跃条件
  2. 用动态规划记录到达每个位置的最小代价
  3. 从左到右遍历,动态更新可达位置的最小代价

算法步骤:

  • 初始化 dp[i] 表示到达位置 i 的最小代价,dp[0] = 0
  • 维护两个单调栈:
    • stack1:处理条件一(单调递减栈)
    • stack2:处理条件二(单调递增栈)
  • 对每个位置 j,检查能从哪些位置跳到 j,并更新最小代价

算法过程

输入: nums = [3,2,4,4,1], costs = [3,7,6,4,2]

初始状态

位置:    0  1  2  3  4
nums:   [3, 2, 4, 4, 1]
costs:  [3, 7, 6, 4, 2]
dp:     [0, ∞, ∞, ∞, ∞]stack1: []  (单调递减栈 - 处理条件一)
stack2: []  (单调递增栈 - 处理条件二)

步骤1:处理位置0 (nums[0] = 3)

当前位置 j = 0, nums[0] = 3stack1操作:
- 栈为空,直接入栈
- stack1: [0]stack2操作:
- 栈为空,直接入栈  
- stack2: [0]dp状态:[0, ∞, ∞, ∞, ∞]

步骤2:处理位置1 (nums[1] = 2)

当前位置 j = 1, nums[1] = 2stack1操作(条件一):
- nums[stack1.top()] = nums[0] = 3 > nums[1] = 2
- 不满足 nums[i] <= nums[j],不弹出
- stack1: [0, 1]stack2操作(条件二):
- nums[stack2.top()] = nums[0] = 3 > nums[1] = 2 ✓
- 弹出位置0,更新 dp[1] = min(∞, dp[0] + costs[1]) = min(∞, 0 + 7) = 7
- 将位置1入栈
- stack2: [1]dp状态:[0, 7, ∞, ∞, ∞]跳跃路径:0 → 1 (代价7)

步骤3:处理位置2 (nums[2] = 4)

当前位置 j = 2, nums[2] = 4stack1操作(条件一):
- nums[1] = 2 <= nums[2] = 4 ✓,弹出位置1dp[2] = min(∞, dp[1] + costs[2]) = min(∞, 7 + 6) = 13
- nums[0] = 3 <= nums[2] = 4 ✓,弹出位置0  dp[2] = min(13, dp[0] + costs[2]) = min(13, 0 + 6) = 6
- 将位置2入栈
- stack1: [2]stack2操作(条件二):
- nums[1] = 2 < nums[2] = 4,不满足条件二,不弹出
- 将位置2入栈
- stack2: [1, 2]dp状态:[0, 7, 6, ∞, ∞]跳跃路径:0 → 2 (代价6) 或 0 → 1 → 2 (代价13)
最优:0 → 2 (代价6)

步骤4:处理位置3 (nums[3] = 4)

当前位置 j = 3, nums[3] = 4stack1操作(条件一):
- nums[2] = 4 <= nums[3] = 4 ✓,弹出位置2dp[3] = min(∞, dp[2] + costs[3]) = min(∞, 6 + 4) = 10
- 将位置3入栈
- stack1: [3]stack2操作(条件二):
- nums[2] = 4 不大于 nums[3] = 4,不弹出
- 将位置3入栈
- stack2: [1, 2, 3]dp状态:[0, 7, 6, 10, ∞]跳跃路径:0 → 2 → 3 (代价10)

步骤5:处理位置4 (nums[4] = 1)

当前位置 j = 4, nums[4] = 1stack1操作(条件一):
- nums[3] = 4 > nums[4] = 1,不满足条件一,不弹出
- 将位置4入栈
- stack1: [3, 4]stack2操作(条件二):
- nums[3] = 4 > nums[4] = 1 ✓,弹出位置3dp[4] = min(∞, dp[3] + costs[4]) = min(∞, 10 + 2) = 12
- nums[2] = 4 > nums[4] = 1 ✓,弹出位置2dp[4] = min(12, dp[2] + costs[4]) = min(12, 6 + 2) = 8
- nums[1] = 2 > nums[4] = 1 ✓,弹出位置1dp[4] = min(8, dp[1] + costs[4]) = min(8, 7 + 2) = 9
- 最终 dp[4] = 8
- stack2: [4]dp状态:[0, 7, 6, 10, 8]跳跃路径:0 → 2 → 4 (代价8)

最优路径

最终答案:dp[4] = 8最优路径:0 → 2 → 4
详细分析:
- 从位置0跳到位置2:满足条件一 (nums[0]=3 <= nums[2]=4,中间nums[1]=2 < nums[0]=3)
- 从位置2跳到位置4:满足条件二 (nums[2]=4 > nums[4]=1,中间nums[3]=4 >= nums[2]=4)
- 总代价:costs[2] + costs[4] = 6 + 2 = 8

详细代码实现

Java 实现

class Solution {public long minCost(int[] nums, int[] costs) {int n = nums.length;long[] dp = new long[n];// 初始化dp数组Arrays.fill(dp, Long.MAX_VALUE);dp[0] = 0;  // 起始位置代价为0// 两个单调栈Deque<Integer> stack1 = new ArrayDeque<>();  // 处理条件一Deque<Integer> stack2 = new ArrayDeque<>();  // 处理条件二for (int j = 0; j < n; j++) {// 处理条件一:nums[i] <= nums[j] 且中间元素都小于 nums[i]// 单调递减栈,当遇到更大的元素时弹出while (!stack1.isEmpty() && nums[stack1.peek()] <= nums[j]) {int i = stack1.pop();dp[j] = Math.min(dp[j], dp[i] + costs[j]);}stack1.push(j);// 处理条件二:nums[i] > nums[j] 且中间元素都大于等于 nums[i]// 单调递增栈,当遇到更小的元素时弹出while (!stack2.isEmpty() && nums[stack2.peek()] > nums[j]) {int i = stack2.pop();dp[j] = Math.min(dp[j], dp[i] + costs[j]);}stack2.push(j);}return dp[n - 1];}
}

C# 实现

public class Solution {public long MinCost(int[] nums, int[] costs) {int n = nums.Length;long[] dp = new long[n];// 初始化dp数组for (int i = 0; i < n; i++) {dp[i] = long.MaxValue;}dp[0] = 0;  // 起始位置代价为0// 两个单调栈Stack<int> stack1 = new Stack<int>();  // 处理条件一Stack<int> stack2 = new Stack<int>();  // 处理条件二for (int j = 0; j < n; j++) {// 处理条件一:nums[i] <= nums[j] 且中间元素都小于 nums[i]while (stack1.Count > 0 && nums[stack1.Peek()] <= nums[j]) {int i = stack1.Pop();dp[j] = Math.Min(dp[j], dp[i] + costs[j]);}stack1.Push(j);// 处理条件二:nums[i] > nums[j] 且中间元素都大于等于 nums[i]while (stack2.Count > 0 && nums[stack2.Peek()] > nums[j]) {int i = stack2.Pop();dp[j] = Math.Min(dp[j], dp[i] + costs[j]);}stack2.Push(j);}return dp[n - 1];}
}

时间复杂度和空间复杂度

  • 时间复杂度:O(n) - 每个元素最多入栈和出栈一次
  • 空间复杂度:O(n) - dp数组和两个栈的空间
http://www.dtcms.com/wzjs/537839.html

相关文章:

  • 网站开发 pdf 文字版网页设计与网站建设程序作业
  • 网站建设图文长沙县住房和城乡建设局网站
  • 企业建网站程序域名备案网站负责人
  • 厦门网站建设设计公司哪家好网页设计作业代做
  • 专业建站网网站运营推广南昌地宝网首页
  • 有什么网站可以免费看电影新建的网站多长时间在百度搜到
  • 福建建设厅网站天下网商自助建站系统
  • 中国新农村建设网站网站结构有哪几种
  • 石家庄城乡建设厅网站学校网站建设注意点
  • 安徽网站建设服务平台建筑工程网下载
  • 网站下载视频的方法免费域名网站创建
  • 做网站要用多少钱怎么看一个网站哪公司做的
  • 惠州做棋牌网站建设哪家服务好帝国做的电影网站
  • 杭州酒店网站建设电子网站建设ppt模板
  • 网站备案号图标代码实现wordpress百度地图
  • 京津冀协同发展英文网站建设与网站优化
  • 诚信企业品牌网站建设郑州做花店网站
  • 简单干净的网站苏州企业网站建设设计制作公司
  • 石家庄专业网站设计wordpress always
  • 个人响应式网站建设wordpress唱片公司模板
  • 上海做网站较好的公司西安企业网站建设托管
  • 自己找网站开发项目app开发和维护费用
  • vs做网站应该新建什么韶关做网站的
  • 兼职网网站建设方案建议书重庆seo网络优化师
  • 门户网站建设 考核烟台网站制作人才招聘
  • 项目管理软件worktile烟台网站快速优化排名
  • 可以免费建设网站产品推广怎么写
  • 网站系统怎么做的物流网站给做软件
  • 手机端微网站设计模板如何注销网站备案
  • 一键搭建网站工具微信手机网站设计6