zoukankan      html  css  js  c++  java
  • 5314跳跃游戏IV

    题目:给你一个整数数组 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)
    View Code

    法二: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
    View Code

    ttt

  • 相关阅读:
    SQLServer ---------- 安装SQLServer后报错解决
    linux --------- linux系统 安装tomcat
    linux -------------- Linux系统安装jdk
    linux ------ 在Vm 安装 centos系统
    linux ----------- 在VM上 的安装 centos
    Objective-C 图片处理
    Objective-C 符号化
    Objective-C
    Objective-C Core Animation深入理解
    C/C++ 内存对齐
  • 原文地址:https://www.cnblogs.com/xxswkl/p/12288691.html
Copyright © 2011-2022 走看看