IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 算法_贪心算法篇 -> 正文阅读

[数据结构与算法]算法_贪心算法篇

LeetCode_跳跃游戏

本文通过跳跃游戏的几个算法例题总结一下相关贪心算法,开始学习的阶段,借鉴好的算法思路并学习,也巩固一下最近学习的算法。(后续遇到贪心算法会续更~~)



前言

贪心算法——在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,它所做出的仅仅是在某种意义上的局部最优解。

贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择。必须注意的是,贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性(即某个状态以后的过程不会影响以前的状态,只与当前状态有关。)

贪心算法的基本思路:

  • 建立数学模型来描述问题
  • 把求解的问题分成若干个子问题
  • 对每个子问题求解,得到子问题的局部最优解
  • 把子问题的解局部最优解合成原来问题的一个解

该算法存在的问题:

  • 不能保证求得的最后解是最佳的
  • 不能用来求最大值或最小值的问题
  • 只能求满足某些约束条件的可行解的范围

贪心策略适用的前提是:局部最优策略能导致产生全局最优解。


一、跳跃游戏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 * 104
0 <= nums[i] <= 105

大致思路:
分析:
由题目得出,要想到达最后一个下标,得满足两个条件:

1、假设每个位置都能跳到,那么只需要遍历数组,看看有没有位置能直接通过这个位置上的数字跳到结尾。
比如[2,3,1,1,4],我们遍历数字,看看哪个位置可以跳到最后,可以发现第三个位置的数字是2,所以可以通过第三个位置跳到最后的下标,数组成立。

2、上述假设成立的还有个条件就是每个位置是否都能跳到。
比如[3,2,1,0,4],按照上面的逻辑,第三个位置可以跳跃1步到第4个位置,但第4个位置不可跳跃,因此不能到达最后位置。


public class CanJumpGames {
//方法1
    public boolean canJump(int[] nums) {
    //n为步数,初始为1
        int step = 1;
        //从倒数第2位开始检验
        for (int i = nums.length - 2; i >= 0; i--) {
        //nums[i]大于或等于step,说明从此位置可以跳到最后一位
            if (nums[i] >= step) {
                step = 1;
            } else {
            //若nums[i]小于step,说明从此位置不能跳到最后一位,则step++,向前遍历查看其它位置是否能跳到最后一位
                step++;
            }
            //遍历到位置0时,且跳跃的步数大于1,则返回false
            if (i == 0 && step > 1) {
                return false;
            }
        }
        return true;
    }
    
//方法2
public boolean canJump(int[] nums) { 
        //能到达的最大位置k 
        int k =0; 
        //获取数组长度 
        int len = nums.length; 
        //遍历数组 
        for(int i=0;i<len ;i++){ 
            if(k<i) return false; 
            k=Math.max(k,i+nums[i]); 
            if (k >= len -1) { 
            //减少循环次数
             return true; 
            } 
        } 
        return false; 
    } 
}

二、跳跃游戏II

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

示例 1:
输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

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

大致思路:
简单分析:[2,3,1,1,4]中,第一步数字是2,可以跳到数字是3和数字是1的两个地方,贪心选择大的,即选择跳到3那步;从3即下标1的位置可以跳到数字分别是1,1,4的三个地方,贪心选择4;而4即为最后一位,最终结果是需要跳2次。


public class CanJump2 {
//  贪心
    public int jump(int[] nums) {
//        若数组长度为1,则不需要跳跃
        if(nums.length == 1) {return 0;}
//        每次跳跃的开始位置
        int reach = 0;
//        跳跃后到达的位置的数值,开始在下标为0的位置
        int nextreach = nums[0];
//        跳跃步数
        int step = 0;
        for(int i = 0;i<nums.length;i++){
//            取目前最大的跳跃
            nextreach = Math.max(i+nums[i],nextreach);
            if(nextreach >= nums.length-1) {return (step+1);}
            if(i == reach){
//              当nextreach下标的值不能跳跃到最后一位时,step++且让reach到达nextreach下标的位置
                step++;
                reach = nextreach;
            }
        }
        return step;
    }

    //动态规划 较占用内存,消耗时间较长
    public int jump01(int[] nums) {
        int[] dp = new int[nums.length];//dp[i] 为到达 i 位置的最小跳数
        dp[0] = 0;//到达下标0的最小跳数是0
        for (int i = 1; i < nums.length; i++) {
            dp[i] = Integer.MAX_VALUE;//先把到达此步数的设置为无限大,作为下面取最小步数时不会有误的临界值
            for (int j = 0; j < i; j++) {
                if (i - j <= nums[j]) {
//                    选择 i 之前的能跳到 i 的所有位置 j 中, dp[j] 值最小的位置 j 作为上一步要跳到 i 的位置
                    dp[i] = Math.min(dp[i], dp[j] + 1);//dp[i]=dp[j]+1 ,从 j 跳到 i ,步数加1
                }
            }
        }
//        dp[nums.length-1] 即到达最后一个位置的最小跳数
        return dp[nums.length - 1];
    }
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-07 12:20:33  更:2021-08-07 12:23:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 19:38:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码