代码练习14---贪心算法

我们只需遍历一次数组,实时更新当前的最小价格和最大利润。这是一个典型的贪心策略,因为我们总是试图通过当前的选择来尽可能获取最大利益。

贪心算法是一种设计算法的策略,其核心思想是每一步都做出当前看起来最优的选择,以期通过一系列的局部最优解最终达到全局最优解。贪心算法的基本原则是:

  1. 选择:在每一步中选择当前最优的选项。
  2. 可行性:确保每一步的选择都是可行的,即能够满足问题的约束条件。
  3. 局部最优:每一步选择的最优解不会影响后续步骤的选择。
  4. 全局最优:通过局部最优的选择,能够达到全局最优的解。

题目一、买卖股票的最佳时机 

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

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

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

C++核心代码

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        //检查数组是否为空
        if(prices.empty()) return 0;
        int minprice = prices[0];
        int maxProfit = 0;
        for(int i=1;i<prices.size();i++){
            int currentprice = prices[i];
            int currentProfit = currentprice - minprice;
            maxProfit = std::max(maxProfit,currentProfit);
            minprice = std::min(minprice,currentprice);
        }
        return maxProfit;

    }
};

题目二、跳跃游戏--是否可以跳到最后

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

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

C++核心代码:

class Solution {
public:
    bool canJump(vector<int>& nums) {
        int farthest = 0;
        for(int i =0;i<nums.size();i++){
            if(i>farthest){
                return false;
            }
            farthest=std::max(farthest,i+nums[i]);
            if(farthest >= nums.size()-1){
                return true;
            }
        }
        return false;
     

    }
};

代码解释

  1. 初始化:

    • farthest 变量表示当前能到达的最远位置,初始化为 0。
  2. 遍历数组:

    • 遍历数组的每个下标 i
    • 如果当前下标 i 超出了 farthest,说明从起始位置无法到达该位置,返回 false
    • 更新 farthesti + nums[i] 和现有 farthest 中的最大值。
    • 如果 farthest 达到或超过最后一个下标 n - 1,返回 true
  3. 返回:

    • 如果遍历完成后无法到达最后一个下标,返回 false

这个贪心算法的时间复杂度是 O(n),空间复杂度是 O(1),因为我们只用常量级别的额外空间来存储 farthest 变量。

题目三、跳跃游戏2-找到最小跳跃次数

给定一个长度为 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]

C++核心代码: 

class Solution {
public:
    int jump(vector<int>& nums) {
        int n = nums.size();
        if(n <= 1) return 0;
        int jumps = 0;
        int currentEnd = 0;
        int farstest = 0;

        for(int i = 0;i<n-1;++i){
            farstest = std::max(farstest,i+nums[i]);
            if(i == currentEnd){
                ++jumps;
                currentEnd = farstest;
                if(currentEnd >=n-1){
                    return jumps;
                }
            }
        }
        return -1;

    }
};

代码解释

  1. 初始化:

    • jumps:记录跳跃次数,初始化为 0
    • currentEnd:当前跳跃范围的终点。
    • farthest:能到达的最远位置。
  2. 遍历数组:

    • 遍历数组中的每个位置 i,更新 farthest 为当前能到达的最远位置(i + nums[i])。
    • 如果当前索引 i 达到 currentEnd(即当前跳跃范围的终点),则需要增加跳跃次数,并更新 currentEndfarthest
    • 如果更新后的 currentEnd 能到达最后一个下标 n - 1,则返回当前的跳跃次数 jumps
  3. 返回结果:

    • 如果遍历结束后,能到达最后一个位置,则返回 jumps。理论上不应该到达 -1,因为题目保证可以到达最后一个位置。

题目四、 划分字母区间

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

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

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

C++核心代码 

class Solution {
public:
    vector<int> partitionLabels(string s) {
        std::unordered_map<char, int>lastPosition;
        int n = s.size();

        for(int i=0;i<n;++i){
            lastPosition[s[i]]=i;

        }
        std::vector<int> result;
        int start = 0;
        int end = 0;
        for(int i= 0;i<n;++i){
            end = std::max(end,lastPosition[s[i]]);
            if(i == end){
                result.push_back(end-start+1);
                start = i+1;
            }
        }
        return result;

    }
};

代码解释

  1. 记录字符的最后出现位置

    • 遍历字符串 s,并将每个字符的最后出现位置存储在 lastPosition 哈希表中。
  2. 划分片段

    • 遍历字符串 s,维护一个 end 变量表示当前片段的结束位置。
    • 对于每个字符,更新 end 为当前字符的最后出现位置(使用 std::max)。
    • 当遍历到位置 i 等于 end 时,表示当前片段结束。记录片段的长度并更新 start 为下一个片段的起始位置。
  3. 返回结果

    • 将每个片段的长度存储在 result 向量中,并最终返回该向量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值