Python每日一练(20230511) 跳跃游戏 I\II\III\IV

简介: Python每日一练(20230511) 跳跃游戏 I\II\III\IV

1. 跳跃游戏 Jump Game I


给定一个非负整数数组 nums ,你最初位于数组的 第一个下标


数组中的每个元素代表你在该位置可以跳跃的最大长度。


判断你是否能够到达最后一个下标。


示例 1:

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

输出:true

解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。


示例 2:

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

输出:false

解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。


提示:

   1 <= nums.length <= 3 * 10^4

   0 <= nums[i] <= 10^5


代码1: 贪心算法

class Solution:
    def canJump(self, nums):
        n = len(nums)
        max_pos = 0
        for i in range(n):
            if i > max_pos:
                return False
            max_pos = max(max_pos, i+nums[i])
        return True
# %%
s = Solution()
print(s.canJump(nums = [2,3,1,1,4]))
print(s.canJump(nums = [3,2,1,0,4]))


代码2:回溯算法

class Solution:
    def canJump(self,nums):
        def backtrack(pos):
            if pos == len(nums) - 1:
                return True
            furthestJump = min(pos + nums[pos], len(nums) - 1)
            for nextPos in range(furthestJump, pos, -1):
                if backtrack(nextPos):
                    return True
            return False
        return backtrack(0)
# %%
s = Solution()
print(s.canJump(nums = [2,3,1,1,4]))
print(s.canJump(nums = [3,2,1,0,4]))


代码3: 反向贪心算法

class Solution:
    def canJump(self, nums):
        n = len(nums)
        last_pos = n - 1
        for i in range(n - 2, -1, -1):
            if i + nums[i] >= last_pos:
                last_pos = i
        return last_pos == 0
# %%
s = Solution()
print(s.canJump(nums = [2,3,1,1,4]))
print(s.canJump(nums = [3,2,1,0,4]))

代码4: 动态规划

class Solution:
    def canJump(self, nums):
        n = len(nums)
        dp = [False] * n
        dp[0] = True
        for i in range(1, n):
            for j in range(i):
                if dp[j] and j + nums[j] >= i:
                    dp[i] = True
                    break
        return dp[n-1]
# %%
s = Solution()
print(s.canJump(nums = [2,3,1,1,4]))
print(s.canJump(nums = [3,2,1,0,4]))

输出:

True

False


2. 跳跃游戏 Jump Game II


给你一个非负整数数组 nums ,你最初位于数组的第一个位置。


数组中的每个元素代表你在该位置可以跳跃的最大长度。


你的目标是使用最少的跳跃次数到达数组的最后一个位置。


假设你总是可以到达数组的最后一个位置。


示例 1:

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

输出: 2

解释: 跳到最后一个位置的最小跳跃数是 2。


    从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。


示例 2:

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


输出: 2

提示:

   1 <= nums.length <= 104

   0 <= nums[i] <= 1000

代码1: 贪心算法


class Solution:
    def jump(self, nums):
        if len(nums) <= 1:
            return 0
        end = 0 + nums[0]
        start = 0
        step = 1
        maxDis = 0 + nums[0]
        while end < len(nums) - 1:
            for i in range(start + 1, end + 1):
                maxDis = max(maxDis, nums[i] + i)
            start = end
            end = maxDis
            step += 1
        return step
# %%
s = Solution()
print(s.jump(nums = [2,3,1,1,4]))
print(s.jump(nums = [2,3,0,1,4]))

代码2: 贪心算法

class Solution:
    def jump(self, nums):
        end, max_pos, steps = 0, 0, 0
        for i in range(len(nums) - 1):
            max_pos = max(max_pos, i + nums[i])
            if i == end:
                end = max_pos
                steps += 1
        return steps
# %%
s = Solution()
print(s.jump(nums = [2,3,1,1,4]))
print(s.jump(nums = [2,3,0,1,4]))


代码3: 动态规划

class Solution:
    def jump(self,nums):
        n = len(nums)
        dp = [0] * n
        for i in range(1, n):
            dp[i] = float('inf')
            for j in range(i):
                if j + nums[j] >= i:
                    dp[i] = min(dp[i], dp[j] + 1)
        return dp[n-1]
# %%
s = Solution()
print(s.jump(nums = [2,3,1,1,4]))
print(s.jump(nums = [2,3,0,1,4]))


输出:

2

2


3. 跳跃游戏 Jump Game III


这里有一个非负整数数组 arr,你最开始位于该数组的起始下标 start 处。当你位于下标 i 处时,你可以跳到 i + arr[i] 或者 i - arr[i]。


请你判断自己是否能够跳到对应元素值为 0 的 任一 下标处。


注意,不管是什么情况下,你都无法跳到数组之外。


示例 1:

输入:arr = [4,2,3,0,3,1,2], start = 5

输出:true


解释:

到达值为 0 的下标 3 有以下可能方案:  

下标 5 -> 下标 4 -> 下标 1 -> 下标 3  

下标 5 -> 下标 6 -> 下标 4 -> 下标 1 -> 下标 3  


示例 2:

输入:arr = [4,2,3,0,3,1,2], start = 0

输出:true  


解释:

到达值为 0 的下标 3 有以下可能方案:  

下标 0 -> 下标 4 -> 下标 1 -> 下标 3


示例 3:

输入:arr = [3,0,2,1,2], start = 2

输出:false

解释:无法到达值为 0 的下标 1 处。  


提示:

   1 <= arr.length <= 5 * 10^4

   0 <= arr[i] < arr.length

   0 <= start < arr.length


代码: dfs\bfs


class Solution:
    def canReach_dfs(self, arr, start):
        visited = set() # 存储已经访问过的节点
        def dfs(index):
            # 判断是否到达了值为 0 的位置
            if arr[index] == 0:
                return True
            # 标记当前节点为已访问
            visited.add(index)
            # 向左侧跳跃
            if index - arr[index] >= 0 and index - arr[index] not in visited:
                if dfs(index - arr[index]):
                    return True
            # 向右侧跳跃
            if index + arr[index] < len(arr) and index + arr[index] not in visited:
                if dfs(index + arr[index]):
                    return True
            # 无法到达值为 0 的位置
            return False
        return dfs(start)
    def canReach_bfs(self, arr, start):
        from collections import deque
        queue = deque([start])
        visited = set([start])
        while queue:
            index = queue.popleft()
            # 判断是否到达了值为 0 的位置
            if arr[index] == 0:
                return True
            # 向左侧跳跃
            if index - arr[index] >= 0 and index - arr[index] not in visited:
                queue.append(index - arr[index])
                visited.add(index - arr[index])
            # 向右侧跳跃
            if index + arr[index] < len(arr) and index + arr[index] not in visited:
                queue.append(index + arr[index])
                visited.add(index + arr[index])
        # 无法到达值为 0 的位置
        return False
# %%
s = Solution()
print(s.canReach_dfs(arr = [4,2,3,0,3,1,2], start = 5))
print(s.canReach_bfs(arr = [4,2,3,0,3,1,2], start = 5))
print(s.canReach_dfs(arr = [4,2,3,0,3,1,2], start = 0))
print(s.canReach_bfs(arr = [4,2,3,0,3,1,2], start = 0))
print(s.canReach_dfs(arr = [3,0,2,1,2], start = 2))
print(s.canReach_bfs(arr = [3,0,2,1,2], start = 2))


输出:

True

True

True

True

False

False


4. 跳跃游戏 Jump Game IV


给你一个整数数组 arr ,你一开始在数组的第一个元素处(下标为 0)。


每一步,你可以从下标 i 跳到下标 i + 1 、i - 1 或者 j :


   i + 1 需满足:i + 1 < arr.length

   i - 1 需满足:i - 1 >= 0

   j 需满足:arr[i] == arr[j] 且 i != j


请你返回到达数组最后一个元素的下标处所需的 最少操作次数 。


注意:任何时候你都不能跳到数组外面。


示例 1:

输入:arr = [100,-23,-23,404,100,23,23,23,3,404]

输出:3

解释:那你需要跳跃 3 次,下标依次为 0 --> 4 --> 3 --> 9 。下标 9 为数组的最后一个元素的下标。


示例 2:

输入:arr = [7]

输出:0

解释:一开始就在最后一个元素处,所以你不需要跳跃。


示例 3:

输入:arr = [7,6,9,6,9,6,9,7]

输出:1

解释:你可以直接从下标 0 处跳到下标 7 处,也就是数组的最后一个元素处。


提示:

   1 <= arr.length <= 5 * 10^4

   -10^8 <= arr[i] <= 10^8

代码1: bfs

from collections import deque
class Solution:
    def minJumps(self, arr):
        n = len(arr)
        if n == 1:
            return 0
        # 将相同值的位置加入同一个集合中
        value2index = {}
        for i, value in enumerate(arr):
            if value not in value2index:
                value2index[value] = set()
            value2index[value].add(i)
        # BFS 开始前的初始化
        queue = deque([(0, 0)]) # 存储节点的队列,第一项为节点编号,第二项为到达该节点的最少操作数
        visited = set() # 存储已经访问过的节点
        visited.add(0)
        # BFS 遍历
        while queue:
            index, step = queue.popleft()
            if index == n - 1:
                return step
            # 向左侧跳跃
            if index - 1 >= 0 and index - 1 not in visited:
                queue.append((index - 1, step + 1))
                visited.add(index - 1)
            # 向右侧跳跃
            if index + 1 < n and index + 1 not in visited:
                queue.append((index + 1, step + 1))
                visited.add(index + 1)
            # 跳到同值的位置
            if arr[index] in value2index:
                for j in value2index[arr[index]]:
                    if j not in visited:
                        queue.append((j, step + 1))
                        visited.add(j)
                del value2index[arr[index]] # 避免重复访问
        return -1 # 无法到达终点
# %%
s = Solution()
print(s.minJumps(arr = [100,-23,-23,404,100,23,23,23,3,404]))
print(s.minJumps(arr = [7]))
print(s.minJumps(arr = [7,6,9,6,9,6,9,7]))


代码2: bfs + 贪心算法

from collections import deque
class Solution:
    def minJumps(self, arr):
        n = len(arr)
        if n == 1:
            return 0
        # 构建同值位置哈希表
        value2index = {}
        for i, value in enumerate(arr):
            if value not in value2index:
                value2index[value] = []
            value2index[value].append(i)
        # BFS 开始前的初始化
        queue = deque([0])
        visited = set([0])
        step = 0
        # BFS 遍历
        while queue:
            size = len(queue)
            for _ in range(size):
                index = queue.popleft()
                # 判断是否到达终点
                if index == n - 1:
                    return step
                # 跳到同值位置
                if arr[index] in value2index:
                    for j in value2index[arr[index]]:
                        if j != index and j not in visited:
                            queue.append(j)
                            visited.add(j)
                    del value2index[arr[index]]
                # 向左侧跳跃
                if index - 1 >= 0 and index - 1 not in visited:
                    queue.append(index - 1)
                    visited.add(index - 1)
                # 向右侧跳跃
                if index + 1 < n and index + 1 not in visited:
                    queue.append(index + 1)
                    visited.add(index + 1)
            step += 1
        return -1 # 无法到达终点
# %%
s = Solution()
print(s.minJumps(arr = [100,-23,-23,404,100,23,23,23,3,404]))
print(s.minJumps(arr = [7]))
print(s.minJumps(arr = [7,6,9,6,9,6,9,7]))



输出:

3

0

1







目录
相关文章
|
2月前
|
IDE 开发工具 Python
Python扑克游戏编程---摸大点
Python扑克游戏编程---摸大点
60 1
|
3月前
|
Python
python编写下象棋游戏|4-14
python编写下象棋游戏|4-14
|
3月前
|
人工智能 算法 图形学
总有一个是你想要的分享40个Python游戏源代码
这是一系列基于Python开发的游戏项目集合,包括中国象棋、麻将、足球、坦克大战、扑克等多种类型游戏,运用了Pygame等库实现图形界面与AI算法。此外还包含迷宫、数独、推箱子等益智游戏及经典游戏如《仙剑奇侠传二战棋版》和《星露谷物语》的Python版本,适合编程学习与娱乐。
129 11
|
2月前
|
数据采集 前端开发 Python
Python pygame 实现游戏 彩色 五子棋 详细注释 附源码 单机版
Python pygame 实现游戏 彩色 五子棋 详细注释 附源码 单机版
79 0
|
17天前
|
存储 数据挖掘 开发者
Python编程入门:从零到英雄
在这篇文章中,我们将一起踏上Python编程的奇幻之旅。无论你是编程新手,还是希望拓展技能的开发者,本教程都将为你提供一条清晰的道路,引导你从基础语法走向实际应用。通过精心设计的代码示例和练习,你将学会如何用Python解决实际问题,并准备好迎接更复杂的编程挑战。让我们一起探索这个强大的语言,开启你的编程生涯吧!
|
23天前
|
机器学习/深度学习 人工智能 TensorFlow
人工智能浪潮下的自我修养:从Python编程入门到深度学习实践
【10月更文挑战第39天】本文旨在为初学者提供一条清晰的道路,从Python基础语法的掌握到深度学习领域的探索。我们将通过简明扼要的语言和实际代码示例,引导读者逐步构建起对人工智能技术的理解和应用能力。文章不仅涵盖Python编程的基础,还将深入探讨深度学习的核心概念、工具和实战技巧,帮助读者在AI的浪潮中找到自己的位置。
|
23天前
|
机器学习/深度学习 数据挖掘 Python
Python编程入门——从零开始构建你的第一个程序
【10月更文挑战第39天】本文将带你走进Python的世界,通过简单易懂的语言和实际的代码示例,让你快速掌握Python的基础语法。无论你是编程新手还是想学习新语言的老手,这篇文章都能为你提供有价值的信息。我们将从变量、数据类型、控制结构等基本概念入手,逐步过渡到函数、模块等高级特性,最后通过一个综合示例来巩固所学知识。让我们一起开启Python编程之旅吧!
|
23天前
|
存储 Python
Python编程入门:打造你的第一个程序
【10月更文挑战第39天】在数字时代的浪潮中,掌握编程技能如同掌握了一门新时代的语言。本文将引导你步入Python编程的奇妙世界,从零基础出发,一步步构建你的第一个程序。我们将探索编程的基本概念,通过简单示例理解变量、数据类型和控制结构,最终实现一个简单的猜数字游戏。这不仅是一段代码的旅程,更是逻辑思维和问题解决能力的锻炼之旅。准备好了吗?让我们开始吧!
|
10天前
|
Python
Python编程入门:从零开始的代码旅程
本文是一篇针对Python编程初学者的入门指南,将介绍Python的基本语法、数据类型、控制结构以及函数等概念。文章旨在帮助读者快速掌握Python编程的基础知识,并能够编写简单的Python程序。通过本文的学习,读者将能够理解Python代码的基本结构和逻辑,为进一步深入学习打下坚实的基础。
|
14天前
|
数据采集 存储 数据处理
Python中的多线程编程及其在数据处理中的应用
本文深入探讨了Python中多线程编程的概念、原理和实现方法,并详细介绍了其在数据处理领域的应用。通过对比单线程与多线程的性能差异,展示了多线程编程在提升程序运行效率方面的显著优势。文章还提供了实际案例,帮助读者更好地理解和掌握多线程编程技术。