【LeetCode Hot100 贪心算法】 买卖股票的最佳时机、跳跃游戏、划分字母区间

贪心算法

买卖股票的最佳时机

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

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

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

示例 1:

输入:[7,1,5,3,6,4]

输出:5

解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。

注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

思路

如果第 i i i 天卖出股票,则最大利润为(该天的股价-前面天数中最小的股价),然后与已知的最大利润比较,如果大于则更新当前最大利润的值。

代码

java 复制代码
class Solution {
    public int maxProfit(int[] prices) {
        int cost = Integer.MAX_VALUE, profit = 0;
        for (int i = 0; i < prices.length; i++) {
            cost = Math.min(cost, prices[i]);
            profit = Math.max(profit, prices[i] - cost);
        }
        return profit;
    }
}

买卖股票的最佳时机II

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。

返回 你能获得的 最大 利润 。

示例 1:

输入:prices = [7,1,5,3,6,4]

输出:7

解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4。

随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3。

最大总利润为 4 + 3 = 7 。

思路

分解成每天都买卖,但是只在最后的结果中加入正的,局部最优->全局最优。

代码

注意 i 从 1 开始

java 复制代码
class Solution {
    public int maxProfit(int[] prices) {
        int profit = 0;
        for (int i = 1; i< prices.length; i++) {
            profit += Math.max(prices[i] - prices[i-1], 0);
        }
        return profit;
    }
}

跳跃游戏

给你一个非负整数数组 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 , 所以永远不可能到达最后一个下标。

思路

确定从第一个位置开始,能够跳跃到的范围有多少,如果这个范围能够覆盖到数组的最后一个位置,那么就可以范围true。

代码

java 复制代码
class Solution {
    public boolean canJump(int[] nums) {
        int cover = 0; // 覆盖范围
        // 遍历的范围是cover内
        for (int i = 0; i <= cover; i++) {
            // 遍历到一个位置,就从上一个cover和该位置能够到达的最远位置取最大值
            cover = Math.max(cover, i + nums[i]);
            if (cover >= nums.length - 1) {
                // 如果能够覆盖到数组的最后一个位置
                return true;
            }
        }
        return false;
    }
}

跳跃游戏II

在上一题的基础上,要求返回最少跳跃次数。

示例 1:

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

输出: 2

解释: 跳到最后一个位置的最小跳跃数是 2。

从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

思路

代码

java 复制代码
class Solution {
    public int jump(int[] nums) {
        int curRight = 0;   // 已经造桥的右端点
        int nextRight = 0;  // 下一步造桥最远的端点
        int ans = 0;  // 答案
        // for 循环中 i < nums.length - 1
        // 因为开始的时候边界时第0个位置,ans已经加过一次1了,最后末尾的时候不用计算步数了
        for (int i = 0; i < nums.length - 1; i++) {
            nextRight = Math.max(nextRight, i + nums[i]);
            if (i == curRight) {   // 到达已建造的桥的右端点
                curRight = nextRight;  // 建造桥
                ans++;
            }
        }
        return ans;
    }
}

划分字母区间

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

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

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

示例 1:

输入:s = "ababcbacadefegdehijhklij"

输出:[9,7,8]

解释:

划分结果为 "ababcbaca"、"defegde"、"hijhklij" 。

每个字母最多出现在一个片段中。

像 "ababcbacadefegde", "hijhklij" 这样的划分是错误的,因为划分的片段数较少。

示例 2:

输入:s = "eccbbbbdec"

输出:[10]

思路

先用一个hash数组把字符串中每一个字母出现的最远位置下标存储在hash数组中。

遍历字符串,更新当前要划分的区间的最远距离(当前最远距离与该位置字母的最远位置下标取最大值)

然后判断此时的最远位置是否是当前位置,如果是说明已经找到了一个划分的区间。

结合代码随项目的思路来解题

代码

java 复制代码
class Solution {
    public List<Integer> partitionLabels(String s) {
        int[] hash = new int[26];

        for (int i = 0; i < s.length(); i++) {
            // 求某个字母的最远位置;使用hash来记录;
            // s.charAt(i) - 'a'是字母的索引,i是这个字母目前的最远位置
            hash[s.charAt(i) - 'a'] = i;
        }

        int left = 0, right = 0;
        List<Integer> ans = new ArrayList<>();

        for (int i = 0; i < s.length(); i++) {
            // 现有的右边界和当前位置字母的最远出现位置求max
            right = Math.max(right, hash[s.charAt(i) - 'a']);
            // i == right 说明找到了一个分割点
            if (i == right) {
                ans.add(right - left + 1);
                left = right + 1; 
            }  
        }
        return ans;
    }
}
相关推荐
弓.长.2 小时前
【leetcode刷题】:双指针篇(有效三角形的个数、和为s的两个数)
c++·算法·leetcode
洛洛英英5 小时前
电脑提示directx错误导致玩不了游戏怎么办?dx出错的解决方法
游戏·电脑
_WndProc7 小时前
【C++/控制台】2048小游戏
开发语言·c++·游戏·游戏程序
hvinsion7 小时前
HTML 迷宫游戏
前端·游戏·html
小冯的编程学习之路8 小时前
【LeetCode】:稀疏相似度【困难】
c++·算法·leetcode
星晖云游者8 小时前
【AI游戏】使用强化学习玩 Flappy Bird:从零实现 Q-Learning 算法(附完整资源)
人工智能·游戏·pygame
AQin101210 小时前
【Leetcode·中等·数组】59. 螺旋矩阵 II(spiral matrix ii)
算法·leetcode·矩阵·数组
Cosmoshhhyyy12 小时前
LeetCode:3297. 统计重新排列后包含另一个字符串的子字符串数目 I(滑动窗口 Java)
java·leetcode
萌の鱼13 小时前
leetcode 53. 最大子数组和
数据结构·c++·算法·leetcode