力扣100题解及笔记 贪心

 目录

1.力扣100题解及笔记 哈希-CSDN博客

2.力扣100题解及笔记 堆-CSDN博客

3.力扣100题解及笔记 栈-CSDN博客

4.力扣100题解及笔记 双指针-CSDN博客

5.力扣100题解及笔记 链表-CSDN博客

6.力扣100题解及笔记 二叉树-CSDN博客

7.力扣100题解及笔记 二分查找-CSDN博客

8.力扣100及题解 滑动窗口&子串-CSDN博客

9.力扣100题解及笔记 回溯-CSDN博客

10.力扣100题解及笔记 dp&多维dp-CSDN博客

11.力扣100题解及笔记 贪心-CSDN博客

12.力扣100题解及笔记 数组-CSDN博客

13.力扣100题解及笔记 技巧-CSDN博客

14.力扣100题解及笔记 矩阵-CSDN博客

15.力扣100题解及笔记 图论-CSDN博客

理论基础

        局部最优推出整体最优

        决策不会影响到之前的状态,即某个状态一旦确定,则不受后续步骤的影响

121.股票

121. 买卖股票的最佳时机

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

 

示例 1:

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
示例 2:

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。
 

提示:

1 <= prices.length <= 105
0 <= prices[i] <= 104
//股票买卖一次,贪心的想法取最左最小值,取最右最大值,差值就是最大利润
class Solution {
    public int maxProfit(int[] prices) {
        int low = Integer.MAX_VALUE;
        int res = 0;
        for(int i = 0; i < prices.length; i++){
            low = Math.min(prices[i], low);
            res = Math.max(prices[i] - low, res);
        }
        return res;
    }
}

55.跳跃

55. 跳跃游戏

给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。

 

示例 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 <= 104
0 <= nums[i] <= 105

每次取最大跳跃步数(取最大覆盖范围)

整体最优解:最后得到整体最大覆盖范围,看是否能到终点

class Solution {
    public boolean canJump(int[] nums) {
        int maxPos = 0;//到当前位置为止,能够跳到的最远位置
        for (int i = 0; i < nums.length; i++) {
            if (i <= maxPos)  maxPos = Math.max(maxPos, i + nums[i]);//可以从前面的位置跳到当前位,当前位置+跳数>最远位置,就更新
            if (maxPos >= nums.length - 1) return true;//可以到达最后一个位置
            }
        return false;
    }
}

45.跳跃2

45. 跳跃游戏 II

给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。

每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处:

0 <= j <= nums[i] 
i + j < n
返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]。


示例 1:

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

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

提示:

1 <= nums.length <= 104
0 <= nums[i] <= 1000
题目保证可以到达 nums[n-1]

每次取最大跳跃步数(取最大覆盖范围)

整体最优解:最后得到整体最大覆盖范围,看是否能到终点

class Solution {
    public int jump(int[] nums) {
        int res = 0;// 跳跃次数
        int cur = 0;//当前cover
        int next = 0;//下一步cover
        // 遍历,直到超过当前能跳到的最远位置,且cover在数组内
        for (int i = 0; i <= cur && cur < nums.length - 1; ++i) {
            next = Math.max(next, i + nums[i]);// 更新 next 
            if (i == cur) { //到达最远位置时,更新 cur 到 next,并增加跳跃次数
                cur = next;
                res++;
            }
        }
        return res;
    }
}

736.划分字母

763. 划分字母区间

给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。

注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。

返回一个表示每个字符串片段的长度的列表。

示例 1:
输入:s = "ababcbacadefegdehijhklij"
输出:[9,7,8]
解释:
划分结果为 "ababcbaca"、"defegde"、"hijhklij" 。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 这样的划分是错误的,因为划分的片段数较少。 
示例 2:

输入:s = "eccbbbbdec"
输出:[10]
 

提示:

1 <= s.length <= 500
s 仅由小写英文字母组成

从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了分割点

class Solution {
    public List<Integer> partitionLabels(String S) {
        List<Integer> list = new LinkedList<>(); // 存放每个分区的长度
        int[] edge = new int[26]; // 记录每个字母最后出现的位置
        char[] chars = S.toCharArray(); // 将字符串转换为字符数组
        // 第一步:记录每个字母最后出现的位置
        for (int i = 0; i < chars.length; i++) {
            edge[chars[i] - 'a'] = i; //减去'a'来计算当前字母的相对位置
        }
        // 第二步:遍历字符串,根据字母的最后出现位置来分区
        int idx = 0; // 当前分区的最远边界
        int last = -1; // 上一个分区的结束位置
        for (int i = 0; i < chars.length; i++) {
            idx = Math.max(idx, edge[chars[i] - 'a']); // 更新当前分区的最远边界
            if (i == idx) { // 当前索引等于分区的最远边界时,表示一个分区结束
                list.add(i - last); // 计算分区长度并添加到列表
                last = i; // 更新上一个分区的结束位置
            }
        }
        return list;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值