跳跃游戏II

题目介绍

力扣45题:https://leetcode-cn.com/problems/jump-game-ii/
给定一个非负整数数组,你最初位于数组的第一个位置。数组中的每个元素代表你在该位置可以跳跃的最大长度。你的目标是使用最少的跳跃次数到达数组的最后一个位置。假设你总是可以到达数组的最后一个位置。
在这里插入图片描述

分析

本题跳跃规则跟上题一致,并且已经保证可以到达最后一个位置,现在是希望得到最小的跳跃步数。要想步数最小,很容易想到的一个思路是,每一步都迈到最大,也就是直接跳到当前能达到的最远位置。这是典型的贪心策略。

但仔细分析就会发现问题:我们每次从i跳到最远farthest,相当于跳过了中间i到farthest之间的那些元素,接下来就只能按farthest位置的步数前进了。如果farthest位置的元素很小(甚至可能为0),而中间被跳过的元素很大,那我们之前的选择明显出现了偏差。每一步的状态会影响到后续的选择,并不是“无后效”的,所以不能用这样简单的贪心策略。

方法一:反向跳跃

们可以尝试用逆向思维来思考,也就是反向跳跃。

现在我们就不是从第一个位置出发了,而是从最后一个位置出发逆推。我们首先可以得到,哪些位置,可以一步直接跳到最后。而为了让步数最少,我们可以选择让最后一次跳跃最远,也就是说,最后一跳之前所在的位置,距离最后最远。这实际上,也是一种贪心策略。

找到最后一步跳跃前所在的位置之后,我们继续贪心地寻找倒数第二步跳跃前所在的位置,以此类推,直到找到数组的开始位置。

代码如下:

// 方法一:反向跳跃
 public int jump1(int[] nums){
     // 定义一个变量保存跳跃步数
     int steps = 0;

     // 定义循环变量
     int curPosition = nums.length - 1;

     // 不停地向前跳跃,以最远的距离
     while (curPosition > 0){
         // 从前到后遍历数组元素,找到当前距离最远的“上一步位置”
         for (int i = 0; i < curPosition; i++){
             if (i + nums[i] >= curPosition){
                 curPosition = i;    // 从前到后,第一次能跳到当前位置的位置,就是最远的上一步位置
                 steps ++;
                 break;
             }
         }
     }
     return steps;
 }

复杂度分析

  • 时间复杂度:O(n^2),其中 n 是数组长度。有两层嵌套循环,在最坏的情况下,数组中的所有元素都是1,那么要寻找的“上一步”有n个,而每次寻找都需要遍历数组中的每个位置。
  • 空间复杂度:O(1)。

方法二:正向跳跃

我们可以回忆起之前的跳跃游戏中的算法,每次都贪心地找到当前位置i最远能到达的位置farthest,但不能直接跳过去,而是依次遍历接下来的每个位置,继续更新farthest。

原因就在于,i与farthest之间的元素,可能在下一步跳得很远。综合两步来看,我们并不能确定当前i这一步跳到最远,两步之后也跳得最远。

那自然可以想到,我们也考虑长远一点,正向推导的时候考虑两步,就可以保证最优了。这还是一个贪心策略。
在这里插入图片描述
那这里有一个问题,第一步选了(下标)0 -> 1,怎么保证如果选0 -> 2之后不会超过去呢?

我们可以看到,第二步,是肯定超不过的,因为我们第一步选下标1,就是因为它第二步跳得远;第三步,如果基于第一步选0 -> 2,想要跳得更远,就一定会有第二步跳到的位置x能跳非常远。我们可以发现,由于x不会超过0 -> 1之后最远的第二步,所以如果可以0 -> 2 -> x,那就一定能0 -> 1 -> x。所以第一步选位置1一定没有问题。

具体实现,我们可以定义双指针:一个farthest,指向当前这一步跳跃的极限位置,它就是以当前位置为基准、跳跃一步的最远位置;另一个nextFarthest,指向下一次跳跃的极限位置,它应该是遍历直到farthest的所有元素,得到基于当前位置跳跃两步的最远位置。遍历数组,每次到达farthest的时候,跳跃次数加1,并把极限位置更新为当前能到达的最远位置。

代码如下:

// 方法二:正向跳跃,考虑能够跳到最远的两步
 public int jump(int[] nums){

     int steps = 0;
     // 定义双指针,指向当前位置跳一步和两步分别能到的最远位置
     int farthest = 0;
     int nextFarthest = farthest;

     // 不停贪心寻找下一步的合适位置
//        while (farthest < nums.length - 1){
         // 遍历currPosition~farthest范围内所有元素,选择第二步跳跃最远的作为当前一步的选择
         for (int i = 0; i < nums.length - 1; i++){
             // 如果比之前第二步最远距离大,更新
             if (i + nums[i] > nextFarthest){
                 nextFarthest = i + nums[i];
             }
             // 添加步数增长条件:处理到farthest
             if (i == farthest){
                 // 当前一步完成
                 steps ++;
                 farthest = nextFarthest;
             }
         }

//        }

     return steps;
 }

复杂度分析

  • 时间复杂度:O(n),其中 n 是数组长度。
  • 空间复杂度:O(1)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我会为您设计一个简单的跳跃游戏。首先,我们需要安装Pygame库。可以使用以下命令在命令行中安装: ``` pip install pygame ``` 接下来,我们需要创建一个窗口并显示游戏界面。请参考以下代码: ```python import pygame # 初始化Pygame pygame.init() # 设置窗口大小 screen_width = 500 screen_height = 500 screen = pygame.display.set_mode((screen_width, screen_height)) # 设置窗口标题 pygame.display.set_caption("Jump Game") # 游戏主循环 running = True while running: # 处理事件 for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # 更新窗口 pygame.display.update() # 退出Pygame pygame.quit() ``` 现在我们已经有了一个空白的窗口,接下来我们需要添加角色和障碍物。请参考以下代码: ```python import pygame import random # 初始化Pygame pygame.init() # 设置窗口大小 screen_width = 500 screen_height = 500 screen = pygame.display.set_mode((screen_width, screen_height)) # 设置窗口标题 pygame.display.set_caption("Jump Game") # 加载角色图片 player_image = pygame.image.load("player.png") player_x = 50 player_y = 400 player_speed = 5 # 加载障碍物图片 obstacle_image = pygame.image.load("obstacle.png") obstacle_x = 500 obstacle_y = 400 obstacle_speed = 3 # 游戏主循环 running = True while running: # 处理事件 for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # 移动角色 keys = pygame.key.get_pressed() if keys[pygame.K_SPACE]: player_y -= player_speed * 2 else: player_y += player_speed # 移动障碍物 obstacle_x -= obstacle_speed if obstacle_x < 0: obstacle_x = 500 obstacle_y = random.randint(200, 400) # 绘制角色和障碍物 screen.blit(player_image, (player_x, player_y)) screen.blit(obstacle_image, (obstacle_x, obstacle_y)) # 更新窗口 pygame.display.update() # 退出Pygame pygame.quit() ``` 现在我们已经有了一个可以跳跃并躲避障碍物的游戏了。接下来可以添加得分系统、音效等元素来丰富游戏体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值