算法——跳跃游戏问题

求最少跳跃次数

给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
leetcode

DP

解题思路:

  • 利用一个数组,表示到达每个位置最少跳跃次数。
  • 遍历数组,然后对每个位置可以跳到的范围内的位置进行状态转移,保留次数少的。
  • 时间复杂度是n方的。
class Solution {
    public int jump(int[] nums) {
        int n  = nums.length;
        int[] f = new int[n];
        Arrays.fill(f, Integer.MAX_VALUE / 2);
        f[0] = 0;
        for(int i = 0; i < n; i++) {
            for(int j = i; j <= nums[i] + i && j < n; j++) {
                // 状态转移,比较从前一个位置跳过来的次数
                f[j] = Math.min(f[i] + 1, f[j]);
            }
        }

        return f[n - 1];
    }
}

贪心

解题思路:维护一个范围内的最少跳跃次数,当超出该范围,那就不得不增加跳跃次数了。

class Solution {
    public int jump(int[] nums) {
        int res = 0;
        int max = 0, end = 0;
        for(int i = 0; i < nums.length - 1; i++) {
            max = Math.max(max, nums[i] + i);
            // 到达一个范围的终点,说明之前一跳不可能超过这个位置,所以跳跃次数必须增加
            if(end == i) {
                res += 1;
                end = max;
            }
        }

        return res;
    }
}

求最高得分

给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。
一开始你在下标 0 处。每一步,你最多可以往前跳 k 步,但你不能跳出数组的边界。也就是说,你可以从下标 i 跳到 [i + 1, min(n - 1, i + k)] 包含 两个端点的任意位置。
你的目标是到达数组最后一个位置(下标为 n - 1 ),你的 得分 为经过的所有数字之和。
请你返回你能得到的 最大得分 。
leetcode

解题思路:这是一道非常常规的单调队列的题。

  • 首先想到利用DP的做法,每个位置的最优解就是前面k个的最优解加上这个位置的分值。
  • 但如是如果每次都去求前面k个解的最大值,时间复杂度就是nk的,这里会超时。
  • 所以,这里其实就是一个滑动窗口,利用单调队列就能快速求窗口内的最大值了。
class Solution {
    public int maxResult(int[] nums, int k) {
        int n = nums.length; 
        Deque<Integer> q = new LinkedList<>();
        int[] f = new int[n];
		// 填入初始值
        f[0] = nums[0];
        q.offerLast(f[0]);
        for(int i = 1; i < n; i++) {
        	// 超出步数的元素出队
            if(i > k && q.peekFirst() == f[i - k - 1]) q.poll();
            // 计算当前值
            f[i] = nums[i] + q.peekFirst();
			// 当前值入队
            while(!q.isEmpty() && q.peekLast() <= f[i]) q.pollLast();
            q.offerLast(f[i]);

        }
        
        return f[n - 1];
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值