算法题(贪心算法)

一、题目

1、跳跃游戏(LC 55)

2、跳跃游戏2 (LC 45)

3、划分字母区间(LC 763)

二、题解

1、跳跃游戏(LC 55)

(1)分析

这道题判断能否从数组的第一个位置跳到最后一个位置,就是看每一步能覆盖到的最远范围。

可以维护一个变量表示当前能到达的最远下标,从头开始遍历每一个位置。在遍历过程中,如果当前位置已经超出了能到达的最远下标,那就说明根本跳不到这里,直接返回 false 就可以。如果能到达当前位置,就用当前位置加上能跳的长度,更新能到达的最远下标。只要一直遍历到数组结束,都没有出现无法到达的情况,就说明一定能跳到最后一位,返回 true 即可。过程中不纠结具体怎么跳,只关注最远覆盖范围。

时间复杂度是 O (n),只需要一次遍历数组。空间复杂度是 O (1),只用了几个变量记录状态,没有额外空间开销。

(2)题解
java 复制代码
class Solution {
    public boolean canJump(int[] nums) {
        int maxIndex = 0;         //可以到达的最大下标
        for(int i = 0; i < nums.length; i++){
            if(maxIndex < i){
                return false;   //到达不了当前位置,返回false
            }
            maxIndex = Math.max(maxIndex, i+nums[i]);  //更新最大下标
        }
        return true;  //循环结束,说明可以到达最大下标
    } 
}

2、跳跃游戏2 (LC 45)

(1)分析

这道题在跳跃游戏的基础上,要求算出跳到终点的最少步数,同样适用贪心算法,在当前能到达的范围内,尽可能跳到最远的地方,以此减少跳跃次数。

使用三个变量来完成整个逻辑,分别记录跳跃次数、当前这一步能到达的最远位置、下一步能到达的最远位置。遍历数组的时候,不断更新下一步能到达的最远位置,当遍历到当前这一步的边界时,就必须再跳一次,这时候把跳跃次数加一,并且把当前边界更新为下一步的最远位置。因为题目保证一定可以到达终点,所以只需要遍历到倒数第二个位置就够了。

时间复杂度是 O (n),一次遍历完成计算。空间复杂度是 O (1),仅使用常数变量。

(2)题解
java 复制代码
class Solution {
    public int jump(int[] nums) {
        int ans = 0;        //步数
        int curEnd = 0;     //当前的位置
        int nextEnd = 0;    //当前可以到达的最大位置
        for(int i = 0; i < nums.length - 1; i++){
            nextEnd = Math.max(nextEnd, i + nums[i]);
            if(i == curEnd){   //此时需要再走一步,到达nextEnd
                curEnd = nextEnd;
                ans++;
            }
        }
        return ans;
    }
}

3、划分字母区间(LC 763)

(1)分析

这道题要把字符串划分成最多的片段,保证同一个字母只出现在一个片段里,最关键的思路就是先确定每个字母最后出现的位置,再用贪心的方式确定分割点。

先遍历一遍字符串,用数组记录下每一个字母最后一次出现的下标。然后再次遍历字符串,不断更新当前片段的结束位置,这个结束位置取当前字母最后出现位置的最大值。当遍历到当前片段的结束位置时,就说明这个片段里所有字母都不会再出现在后面了,此时可以完成一次分割,记录片段长度,再把起点设为下一个位置继续遍历。遍历结束后返回 ans 结果。

时间复杂度是 O (n),只需要两次线性遍历字符串。空间复杂度是 O (1),记录最后位置的数组大小固定,属于常数级空间。

(2)题解
java 复制代码
class Solution {
    public List<Integer> partitionLabels(String s) {
        List<Integer> ans = new ArrayList<>(); //结果集合
        char[] chs = s.toCharArray();      
        int n = chs.length;
        int[] last = new int[26];  //每个字符最后出现的位置
        for(int i = 0; i < n; i++){
            last[chs[i] - 'a'] = i;  //记录每个字符的最后下标
        }

        int start = 0;      //闭区间
        int end = 0;
        for(int i =0; i <n; i++){
            end = Math.max(last[chs[i] -'a'], end); //更新最大下标
            if(i == end){              //此时可以分割
                ans.add(end - start + 1);
                start = end + 1;
            }
        }
        return ans;
    }
}
相关推荐
听你说325 小时前
不迷路、不重扫、不遗漏:库萨科技无人清扫车以空间智能领跑无人环卫赛道
人工智能·科技·算法·机器人
吃好睡好便好5 小时前
在Matlab中绘制三维直方图
开发语言·学习·算法·matlab·信息可视化
故事和你915 小时前
洛谷-【图论2-2】最短路4
开发语言·数据结构·c++·算法·动态规划·图论
我爱cope5 小时前
【力扣hot100:239. 滑动窗口最大值】
算法·leetcode·职场和发展
XINVRY-FPGA5 小时前
XC7Z010-2CLG400I Xilinx Zynq-7000 FPGA
arm开发·嵌入式硬件·算法·fpga开发·硬件工程·dsp开发·fpga
承渊政道5 小时前
【贪心算法】(经典实战应用解析(四):分发饼干、最优除法、跳跃游戏、跳跃游戏Ⅱ、加油站)
数据结构·c++·算法·leetcode·贪心算法·动态规划·哈希算法
m0_629494735 小时前
LeetCode 热题 100-----24.回文链表
数据结构·算法·leetcode·链表
爱怪笑的小杰杰5 小时前
Leaflet 实现轨迹拐角自动圆弧化:基于球面几何的高精度平滑算法
前端·javascript·算法·无人机
ccLianLian5 小时前
图论·刷题总结
算法·深度优先·图论