• 算法——跳跃游戏


    求最少跳跃次数

    给定一个非负整数数组,你最初位于数组的第一个位置。
    数组中的每个元素代表你在该位置可以跳跃的最大长度。
    你的目标是使用最少的跳跃次数到达数组的最后一个位置。
    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];
        }
    }
    
  • 相关阅读:
    随机ID添加
    学生ID查询
    node.js基础
    冒泡排序
    循环判断语句
    vue.js详细教程--优优优
    final注意事项
    HashMap Hashtable区别
    java中间件
    JSP错误页面
  • 原文地址:https://www.cnblogs.com/lippon/p/14155714.html
Copyright © 2020-2023  润新知