2022-08-10:为了给刷题的同学一些奖励,力扣团队引入了一个弹簧游戏机, 游戏机由 N 个特殊弹簧排成一排,编号为 0 到 N-1, 初始有一个小球在编号 0 的弹簧处。若小球在编号为 i 的弹
2022-08-10:为了给刷题的同学一些奖励,力扣团队引入了一个弹簧游戏机,
游戏机由 N 个特殊弹簧排成一排,编号为 0 到 N-1,
初始有一个小球在编号 0 的弹簧处。若小球在编号为 i 的弹簧处,
通过按动弹簧,可以选择把小球向右弹射 jump[i] 的距离,或者向左弹射到任意左侧弹簧的位置,
也就是说,在编号为 i 弹簧处按动弹簧,
小球可以弹向 0 到 i-1 中任意弹簧或者 i+jump[i] 的弹簧(若 i+jump[i]>=N ,则表示小球弹出了机器),
小球位于编号 0 处的弹簧时不能再向左弹。
为了获得奖励,你需要将小球弹出机器。
请求出最少需要按动多少次弹簧,可以将小球从编号 0 弹簧弹出整个机器,即向右越过编号 N-1 的弹簧。
答案2022-08-10:
宽度优先遍历。Index Tree。
时间复杂度:O(N*logN)。
代码用rust编写。代码如下:
fn main() {
let mut jump1: Vec<i32> = vec![2, 5, 1, 1, 1, 1];
let mut jump2 = jump1.clone();
let ans1 = min_jump(&mut jump1);
let ans2 = min_jump2(&mut jump2);
println!("ans1 = {}", ans1);
println!("ans2 = {}", ans2);
}
// 宽度优先遍历
// N*logN
fn min_jump(jump: &mut Vec<i32>) -> i32 {
let n = jump.len() as i32;
let mut queue: Vec<i32> = vec![];
for _ in 0..n {
queue.push(0);
}
let mut l: i32 = 0;
let mut r: i32 = 0;
queue[r as usize] = 0;
r += 1;
let mut it = IndexTree::new(n);
// 1...n初始化的时候 每个位置填上1
for i in 1..n {
it.add(i, 1);
}
let mut step: i32 = 0;
while l != r {
// 队列里面还有东西
// tmp记录了当前层的终止位置!
let tmp = r;
// 当前层的所有节点,都去遍历!
while l < tmp {
let cur = queue[l as usize];
let forward = cur + jump[cur as usize];
if forward >= n {
return step + 1;
}
if it.value(forward) != 0 {
queue[r as usize] = forward;
r += 1;
it.add(forward, -1);
}
// cur
// 1....cur-1 cur
while it.sum(cur - 1) != 0 {
let find0 = find(&mut it, cur - 1);
it.add(find0, -1);
queue[r as usize] = find0;
r += 1;
}
l += 1;
}
step += 1;
}
return -1;
}
fn find(it: &mut IndexTree, mut right: i32) -> i32 {
let mut left = 0;
let mut mid;
let mut find0 = 0;
while left <= right {
mid = (left + right) / 2;
if it.sum(mid) > 0 {
find0 = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return find0;
}
pub struct IndexTree {
tree: Vec<i32>,
n: i32,
}
impl IndexTree {
pub fn new(size: i32) -> Self {
let mut tree: Vec<i32> = vec![];
for _ in 0..size + 1 {
tree.push(0);
}
Self { tree, n: size }
}
pub fn value(&mut self, index: i32) -> i32 {
if index == 0 {
return self.sum(0);
} else {
return self.sum(index) - self.sum(index - 1);
}
}
pub fn sum(&mut self, i: i32) -> i32 {
let mut index = i + 1;
let mut ret = 0;
while index > 0 {
ret += self.tree[index as usize];
index -= index & -index;
}
return ret;
}
pub fn add(&mut self, i: i32, d: i32) {
let mut index = i + 1;
while index <= self.n {
self.tree[index as usize] += d;
index += index & -index;
}
}
}
// 感谢黄汀同学
// 弄出了时间复杂度O(N)的过程
// 和大厂刷题班,第10节,jump game类似
fn min_jump2(jump: &mut Vec<i32>) -> i32 {
let nn = jump.len() as i32;
let mut ans = nn;
let mut next = jump[0];
if next >= nn {
return 1;
}
if next + jump[next as usize] >= nn {
return 2;
}
// dp[i] : 来到i位置,最少跳几步?
let mut dp: Vec<i32> = vec![];
for _ in 0..nn + 1 {
dp.push(nn);
}
// dis[i] : <= i步的情况下,最远能跳到哪?
let mut dis: Vec<i32> = vec![];
for _ in 0..nn {
dis.push(0);
}
// 如果从0开始向前跳,<=1步的情况下,最远当然能到next
dis[1] = next;
// 如果从0开始向前跳,<=2步的情况下,最远可能比next + jump[next]要远,
// 这里先设置,以后可能更新
dis[2] = next + jump[next as usize];
dp[(next + jump[next as usize]) as usize] = 2;
let mut step = 1;
for i in 1..nn {
if i > dis[step as usize] {
step += 1;
}
dp[i as usize] = get_min(dp[i as usize], step + 1);
next = i + jump[i as usize];
if next >= nn {
ans = get_min(ans, dp[i as usize] + 1);
} else if dp[next as usize] > dp[i as usize] + 1 {
dp[next as usize] = dp[i as usize] + 1;
dis[dp[next as usize] as usize] = get_max(dis[dp[next as usize] as usize], next);
}
}
return ans;
}
fn get_max<T: Clone + Copy + std::cmp::PartialOrd>(a: T, b: T) -> T {
if a > b {
a
} else {
b
}
}
fn get_min<T: Clone + Copy + std::cmp::PartialOrd>(a: T, b: T) -> T {
if a < b {
a
} else {
b
}
}
执行结果如下:

2022-08-10:为了给刷题的同学一些奖励,力扣团队引入了一个弹簧游戏机, 游戏机由 N 个特殊弹簧排成一排,编号为 0 到 N-1, 初始有一个小球在编号 0 的弹簧处。若小球在编号为 i 的弹的更多相关文章
- 【刷题】BZOJ 3527 [Zjoi2014]力
Description 给出n个数qi,给出Fj的定义如下: 令Ei=Fi/qi,求Ei. Input 第一行一个整数n. 接下来n行每行输入一个数,第i行表示qi. n≤100000,0<qi ...
- LeetCode刷题总结-数组篇(下)
本期讲O(n)类型问题,共14题.3道简单题,9道中等题,2道困难题.数组篇共归纳总结了50题,本篇是数组篇的最后一篇.其他三个篇章可参考: LeetCode刷题总结-数组篇(上),子数组问题(共17 ...
- leetcode每日刷题计划-简单篇day3
收到swe提前批面试hhh算是ep挂了的后续 努力刷题呀争取今年冲进去! Num 21 合并两个有序链表 Merge Two Sorted Lists 注意新开的链表用来输出结果的是ListNode ...
- C#LeetCode刷题-字典树
字典树篇 # 题名 刷题 通过率 难度 208 实现 Trie (前缀树) 48.6% 中等 211 添加与搜索单词 - 数据结构设计 39.9% 中等 212 单词搜索 II 27.9% ...
- C#LeetCode刷题-数组
数组篇 # 题名 刷题 通过率 难度 1 两数之和 C#LeetCode刷题之#1-两数之和(Two Sum) 43.1% 简单 4 两个排序数组的中位数 C#LeetCode刷题之#4-两个排序数组 ...
- USACO刷题之路,开始了
几天前,重新开始刷题了. 重新刷题有几个原因: 1.曾经的OI经历,如今除了悟性高些.知识多些,大多已经遗忘.不希望真的让之前的OI水平就这么丢了. 2.越来越觉得,刷题真的是一件很开心的事情.大学中 ...
- 杭电acm刷题(3):1062,Text Reverse 标签: 杭电acm 2017-05-15 08:26 126人阅读 评论(0)
Problem Description Ignatius likes to write words in reverse way. Given a single line of text which ...
- LeetCode刷题笔记 - 2022
这篇博客集中整理在LeetCode的刷题记录,方便查阅 258. 各位相加 - 力扣(LeetCode) (leetcode-cn.com) 代码 class Solution { public: i ...
- 好像leeceode题目我的博客太长了,需要重新建立一个. leecode刷题第二个
376. Wiggle Subsequence 自己没想出来,看了别人的分析. 主要是要分析出升序降序只跟临近的2个决定.虽然直觉上不是这样. 455. 分发饼干 ...
- 18.9.10 LeetCode刷题笔记
本人算法还是比较菜的,因此大部分在刷基础题,高手勿喷 选择Python进行刷题,因为坑少,所以不太想用CPP: 1.买股票的最佳时期2 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. ...
随机推荐
- conda Installing on Linux - 搬运
转自:Installing on Linux - conda 23.1.0 documentation Installing on Linux Download the installer: Min ...
- EF6 Code First Migrations
参考地址:https://learn.microsoft.com/en-us/ef/ef6/modeling/code-first/migrations/ 1.启动Migrations Enable- ...
- python计算三角形的三个边的边长,首先计算两个坐标点的距离
# -*- coding:utf-8 -*- """ @author: 14931 @file: trianglearea.py @time: 2023/02/14 @d ...
- kafka的原理及集群部署详解
kafka原理详解 消息队列概述 消息队列分类 点对点 组成:消息队列(Queue).发送者(Sender).接收者(Receiver) 特点:一个生产者生产的消息只能被一个接受者接收,消息一旦被消费 ...
- mac快捷键和win10快捷键和mma快捷手册
不定期更新 来自知乎,b站等 mac下的快捷键 如果你mac接了个不一致的键盘,mac会让你检测,(按左ctrl右边的键,按右ctrl左边的键),之后会进行键位映射,这也太复杂了,我拒绝记录. com ...
- Java 泛型与通配符 定义与使用
一.泛型 定义: 把类型明确的工作推迟到创建对象或调用方法时才明确的类型,简而言之,未明确的数据类型. 类型: 泛型类,泛型方法,方形接口. 格式 泛型类格式:class 类名<E变量>{ ...
- 递推求解DAG最长路径长度及最长路径条数
说明 在一般图中,求解最长路或最短路只能通过最短路算法解决 但是在DAG中,由于不存在环,因此可以通过递推,以线性复杂度计算处最长路或最短路.当然需要首先对有向图进行Tarjan缩点转化为DAG 例题 ...
- LinkedBlockingQueue出入队实现原理
类图概述 由类图可以看出,L是单向链表实现的,有两个ReentrantLock实例用来控制元素入队和出队的原子性,takeLock用来控制只有一个线程可以从队头获取元素,putLock控制只有一个线程 ...
- AcWing 1902. 马拉松
题目链接 每次路程改变只对前后两点间距离有影响,因此每次都判断当前三个点之间的距离之和与去掉中间点的距离哪个更优即可,最后取最大值作为结果输出. #include<iostream> #i ...
- MySQL四种日志binlog/redolog/relaylog/undolog
优质博文:IT-BLOG-CN 一.binlog binlog记录数据库表结构和表数据变更,比如update/delete/insert/truncate/create,它不会记录select.存储着 ...