题目:给你一个整数数组 arr ,你一开始在数组的第一个元素处(下标为 0)。每一步,你可以从下标 i 跳到下标:
    i + 1 满足:i + 1 < arr.length
    i - 1 满足:i - 1 >= 0
    j 满足:arr[i] == arr[j] 且 i != j
请你返回到达数组最后一个元素的下标处所需的 最少操作次数 。注意:任何时候你都不能跳到数组外面。

来源:https://leetcode-cn.com/problems/jump-game-iv/

法一: 自己的超时代码    dfs

思路:利用回溯的方法,把每次要遍历的记入k中,同时记录每个分支遍历过的索引,防止重复遍历,剪枝条件是:如果某次回溯的时候,某个到达个位置的次数大于之前记录的值了,直接结束回溯。这个题无法用dp,解题的时候要快速识别出无法用dp动态规划来解决。或即使用dp也很复杂。

from typing import List
from collections import defaultdict
from functools import lru_cache
class Solution:
def minJumps(self, arr: List[int]) -> int:
# print('3333333333', len(arr))
d = defaultdict(list)
size = len(arr)
for i,j in enumerate(arr):
d[j] = d[j] + [i]
# @lru_cache(None)
memo = defaultdict(lambda : size)
def recursion(index, cou=0, used=[-1,0]):
# 回溯结束条件
if index == size-1:
# print('*' * 8, cou)
return cou
# 加上这个剪枝条件后,仍然超时
# 这个条件是如果现在的cou大于之前记录的值,则直接返回,结束这次回溯
if memo[index] < cou:
print('-'* 30)
return size
# if index == 0:
# k = [1] + d[arr[0]][1:]
# # print('kkkkkkkkkkkkkkkkk')
# else: # used [-1,0]的初始值中的-1是为了处理index=0时的情况
# 这儿之所以取set是因为有重复值的情况,
k = list(set(([index-1] if index-1 not in used else []) \
+ ([index+1] if index+1 not in used else []) \
+ list(set(d[arr[index]]) - set(used))))
# 当k为空的时候说明,两边都走过了,也无法跳跃了,直接返回
if k == []:
return cou
memo[index] = cou
res = size
cou += 1
for j in k:
# 这里是关键,每次回溯的时候,传递下一次要跳到的地方,跳过的步数,以及已经跳过的位置,
# 如果没有这个used,程序会陷入死循环,实际上是为了防止重复遍历
res = min(res, recursion(j, cou=cou, used=used+[j]))
return res
return recursion(index=0)
if __name__ == '__main__':
duixiang = Solution()
# a = duixiang.minJumps(arr = [100,-23,-23,404,100,23,23,23,3,404])
a = duixiang.minJumps(arr = [68,-94,-44,-18,-1,18,-87,29,-6,-87,-27,37,-57,7,
18,68,-59,29,7,53,-27,-59,18,-1,18,-18,-59,-1,-18,
-84,-20,7,7,-87,-18,-84,-20,-27])
print(a)

法二:bfs   别人的代码

思路:这个题是一个非常典型的最短路径问题,天然具有应用bfs的优势,因为在这个最短路径问题中,每走一步都是在向目标靠近,而对于每个位置而言,从出发点第一次到达该位置的步数即到达该点的最小值,所以无需再次遍历,由此便想到用bfs,将要走的位置放在队列的前面,由此便控制住了步数,最先到达末尾的即最短的步数。

from collections import defaultdict
from typing import List
class Solution:
def minJumps(self, arr: List[int]) -> int:
d = defaultdict(list)
n = len(arr)
for i in range(n):
d[arr[i]].append(i)
vis = [0] * n
vis[0] = 1
q = [(0, 0)]
while q:
# i是当前位置的索引,k是走过的步数,
i, k = q.pop(0)
# 遍历当前位置的上一个和下一个,以及可以跳跃的位置
for j in d[arr[i]] + [i - 1, i + 1]:
# 如果出界或者已经遍历过了,直接进行下一个循环
if j < 0 or j >= n or vis[j]:
continue
# 一旦跳到最后一个位置了,则它即为最少的步数,直接返回结果
if j == n - 1:
return k + 1
# 遍历过的标记为1
vis[j] = 1
# 把当前的位置放入队列,并且把步数加1
q.append((j, k + 1))
# 某个值的索引一旦遍历过其中一个后,就置为[],因为其余的索引已经放入队列了,无需再次遍历
# 如果第二次在相同的值之间跳跃,则浪费了步数,肯定不是最短的
d[arr[i]] = []
return 0

ttt

5314跳跃游戏IV的更多相关文章

  1. lintcode: 跳跃游戏 II

    跳跃游戏 II 给出一个非负整数数组,你最初定位在数组的第一个位置. 数组中的每个元素代表你在那个位置可以跳跃的最大长度. 你的目标是使用最少的跳跃次数到达数组的最后一个位置. 样例 给出数组A =  ...

  2. lintcode : 跳跃游戏

    跳跃游戏 给出一个非负整数数组,你最初定位在数组的第一个位置. 数组中的每个元素代表你在那个位置可以跳跃的最大长度. 判断你是否能到达数组的最后一个位置. 样例 A = [2,3,1,1,4],返回 ...

  3. 【LeetCode每天一题】Jump Game II(跳跃游戏II)

    Given an array of non-negative integers, you are initially positioned at the first index of the arra ...

  4. LeetCode(45): 跳跃游戏 II

    Hard! 题目描述: 给定一个非负整数数组,你最初位于数组的第一个位置. 数组中的每个元素代表你在该位置可以跳跃的最大长度. 你的目标是使用最少的跳跃次数到达数组的最后一个位置. 示例: 输入: [ ...

  5. 计蒜客-跳跃游戏二 (简单dp)

    题目链接:https://nanti.jisuanke.com/t/20                                         跳跃游戏二 给定一个非负整数数组,假定你的初始 ...

  6. [Leetcode]44.跳跃游戏Ⅰ&&45.跳跃游戏Ⅱ

    跳跃游戏链接 给定一个非负整数数组,你最初位于数组的第一个位置. 数组中的每个元素代表你在该位置可以跳跃的最大长度. 判断你是否能够到达最后一个位置. 示例 1: 输入: [2,3,1,1,4] 输出 ...

  7. 跳跃游戏 12 · Jump Game 12

    跳跃游戏 1 [抄题]: [思维问题]: [一句话思路]: [输入量]:空: 正常情况:特大:特小:程序里处理到的特殊情况:异常情况(不合法不合理的输入): [画图]: [一刷]: 由于要用itera ...

  8. LeetCode:跳跃游戏【55】

    LeetCode:跳跃游戏[55] 题目描述 给定一个非负整数数组,你最初位于数组的第一个位置.数组中的每个元素代表你在该位置可以跳跃的最大长度.判断你是否能够到达最后一个位置. 示例 1: 输入: ...

  9. 运用NP求解 “跳跃游戏”---计蒜客

    计蒜客里面有一道“跳跃游戏的问题” 给定一个非负整数数组,假定你的初始位置为数组第一个下标. 数组中的每个元素代表你在那个位置能够跳跃的最大长度. 你的目标是到达最后一个下标,并且使用最少的跳跃次数. ...

随机推荐

  1. 【转载】使用driver.findElement(By.id("txtPhoneNum")).getText();获取文本

    今天在写自动化测试脚本的时候要获取一个输入框中的文本写了如下脚本: getAndSwitch("http://cas.minshengnet.com:14080/register/eRegi ...

  2. springboot关闭whitelabel Error page

    当访问不存在的页面时报错: 如何关闭它?有2种方法, 方法1: application.properties中加入server.error.whitelabel.enabled=false 方法2:在 ...

  3. linux----查看系统版本命令

    uname -a 可显示电脑以及操作系统的相关信息 cat /proc/version 说明正在运行的内核版本 cat /etc/issue 显示的是发行版本信息

  4. 每天一点点之javascript(ES6) - Map对象

    1.语法 键/值对的集合. mapObj = new Map() 注:集合中的键和值可以是任何类型.如果使用现有密钥向集合添加值,则新值会替换旧值. 2.属性下表列出了 Map 对象的属性和描述. 构 ...

  5. 每天一点点之laravel框架 - Laravel5.6 + Passport实现Api接口认证

    1.首先通过 Composer 包管理器安装 Passport: composer require laravel/passport 注:如果安装过程中提示需要更高版本的 Laravel:larave ...

  6. POJ 3994:Probability One

    Probability One Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1674   Accepted: 1151 D ...

  7. 04-String——课后作业1:字串加密

    题目:请编写一个程序,加密或解密用户输入的英文字串要求设计思想.程序流程图.源代码.结果截图. 程序设计思想:首先由用户选择是加密还是解密,利用String类中的charAt函数依次取出字串中的字符, ...

  8. Pandas_one-hot encoding与dummy encoding

    Pandas_特征编码 one-hot encoding 基本思想是将离散型特征的每一种取值都看成一种状态,保证每一个取值只会使得一种状态处于激活状态. 编码函数pd.get_dummies() du ...

  9. Linux 下 OpenCV3 安装

    编译安装OpenCV3 从官网下载:http://opencv.org/releases.html 选择一个较新版本的opencv3.X,下载source源代码 下载之后解压,并cd到该文件夹进行编译 ...

  10. Vuex 是什么

    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.Vuex 也集成到 Vue 的官方调试工具  ...