【数据结构与算法】LeetCode: 贪心算法

文章目录

LeetCode: 贪心算法

买卖股票的最佳时机 (Hot100)

买卖股票的最佳时机

买卖只有一次

cpp 复制代码
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int max_profit = 0;
        int min_price = INT_MAX ;
        for(int price : prices){  // ,右边的最大值-左边的最小值为最优值
            max_profit = max(max_profit, price- min_price); 
            min_price = min(min_price,price);
        }

        return max_profit;
    }
};

买卖股票的最佳时机 II

买卖股票的最佳时机 II

买卖可以有多次

cpp 复制代码
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int result = 0;
        for(int i = 1; i < prices.size(); i++)
            result += max(prices[i] - prices[i-1], 0); // 把每天的正收益加起来
        return result;
    }
};

跳跃游戏 (Hot100)

跳跃游戏

能否到达最后一个下标

cpp 复制代码
class Solution {
public:
    bool canJump(vector<int>& nums) {
        int max_pos  = 0 + nums[0]; // i之前的最远可达位置

        for(int i = 1; i < nums.size(); i++){   // 枚举每个位置
            if (i > max_pos) return false;      // i不可达
            max_pos = max(max_pos, i + nums[i]);
        }
        return true;
    }
};

跳跃游戏 II(Hot100)

跳跃游戏 II

到达最后一个下标的最小跳跃次数

cpp 复制代码
class Solution {
public:
    int jump(vector<int> &nums) {
        int ans = 0;    // 跳跃次数
        int start = 0;  // 当前跳跃可达区间左边界
        int end = 0;    // 当前跳跃可达空间右边界

        while (end < nums.size() - 1) {
            int max_pos = 0;    // 能跳到的最远距离
            for (int i = start; i <= end; i++) {
                // 当前可达区间能跳到的最远距离
                max_pos = max(max_pos, i + nums[i]);
            }
            ans++;            // 跳跃
            start = end + 1;  // 更新左边界
            end = max_pos;    // 更新右边界
         
        }
        return ans;
    }
};

划分字母区间 (Hot100)

划分字母区间

统计每一个字符最后出现的位置。

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

cpp 复制代码
class Solution {
public:
    vector<int> partitionLabels(string S) {
        int hash[26] = {0}; // i为字符,hash[i]为字符出现的最后位置
        for (int i = 0; i < S.size(); i++) { // 统计每一个字符最后出现的位置
            hash[S[i] - 'a'] = i;
        }
 
        vector<int> result;
        int left = 0; // 遍历最左下标
        int right = 0;// 已遍历字符最大出现位置
        // 从头遍历字符
        for (int i = 0; i < S.size(); i++) {
            right = max(right, hash[S[i] - 'a']); // 更新已遍历(i之前)字符最大出现位置
            // 如果找到已遍历字符最远出现位置下标和当前下标相等了,则找到了分割点
            if (i == right) { 
                result.push_back(right - left + 1);
                left = i + 1;
            }
        }
        return result;
    }
};

分发饼干

分发饼干

cpp 复制代码
class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        sort(g.begin(), g.end());
        sort(s.begin(), s.end());
        int index = s.size() - 1;                 // 饼干数量
        int result = 0;                           // 喂饱的小孩数量
        for (int i = g.size() - 1; i >= 0; i--) { // 遍历小孩
            if (index >= 0 && s[index] >= g[i]) { // 还有饼干且饼干尺寸大于小孩胃口
                result++;
                index--;
            }
        }
        return result;
    }
};

K次取反后最大化的数组和

K次取反后最大化的数组和

cpp 复制代码
class Solution { 
public:
    int largestSumAfterKNegations(vector<int>& nums, int K) {
    	// 按照绝对值从大到小排列
        sort(nums.begin(), nums.end(), [](int a, int b){return abs(a) > abs(b);}); 
        for(int i = 0; i < nums.size(); i++){
            if(nums[i] < 0 && K > 0){  // 把最小的负数变为正
                nums[i] *= -1;
                K--;
            }
        }
        // 如果K不为0且nums此时都为正数:负负得正抵消
        if(K % 2 == 1) nums[nums.size() - 1] *= -1; // 如果K为奇数
        int result = 0;
        for(int a : nums) result += a;
        return result;
    }
};

合并区间

合并区间

cpp 复制代码
class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>> result;
        // 根据左边界从小到大排序
        sort(intervals.begin(), intervals.end(), [](const vector<int>& a, const vector<int>& b){return a[0] < b[0];});
        // 第一个区间就可以放进结果集里,后面如果重叠,在result上直接合并
        result.push_back(intervals[0]); 
        for (int i = 1; i < intervals.size(); i++) {
            if (result.back()[1] >= intervals[i][0]) { // 发现重叠区间
                // 合并区间,只更新右边界就好,因为是按照左边界排序的
                result.back()[1] = max(result.back()[1], intervals[i][1]); 
            } else { // 区间不重叠 ,直接放入
                result.push_back(intervals[i]); 
            }
        }
        return result;
    }
};

用最少数量的箭引爆气球

用最少数量的箭引爆气球

cpp 复制代码
class Solution {

public:
    int findMinArrowShots(vector<vector<int>>& points) {
        if (points.size() == 0) return 0;
        // 按照左边界从小到大排序
        sort(points.begin(), points.end(), [](vector<int>& a, vector<int>& b){return a[0] < b[0];});

        int result = 1; // points 不为空至少需要一支箭
        for (int i = 1; i < points.size(); i++) {
            if (points[i][0] > points[i - 1][1]) {  // 气球i和气球i-1不挨着
                result++; // 需要加一支箭
            }
            else {  // 气球i和气球i-1挨着
                points[i][1] = min(points[i - 1][1], points[i][1]); // 更新重叠气球最小右边界
            }
        }
        return result;
    }
};

无重叠区间

无重叠区间

cpp 复制代码
class Solution {
public:

    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        if (intervals.size() == 0) return 0;
        //  按照区间左边界从小到大排序
        sort(intervals.begin(), intervals.end(), [](vector<int>& a, vector<int>& b){return a[0] < b[0];});

        int result = 1; // 记录非重叠区间的个数
        // 从左到右,对于重叠的多个区间,优先去掉右边界较大的
        for (int i = 1; i < intervals.size(); i++) {
            if (intervals[i][0] >= intervals[i - 1][1]) { // 区间i不与左边右边界最小的区间重叠
                result++; // 非重叠区间数量+1
            }
            else {  // 区间i与左边的区间重叠
                intervals[i][1] = min(intervals[i - 1][1], intervals[i][1]); // 更新重叠气球最小右边界
            }
        }
        return intervals.size() - result;
    }
};
相关推荐
_Itachi__2 分钟前
LeetCode 热题 100 101. 对称二叉树
算法·leetcode·职场和发展
少了一只鹅13 分钟前
深入理解指针(5)
java·c语言·数据结构·算法
朱剑君44 分钟前
第三天——贪心算法——区间问题
算法·贪心算法
阳洞洞1 小时前
leetcode 15. 三数之和
leetcode·双指针
Mi Manchi262 小时前
力扣热题100之合并两个有序链表
算法·leetcode·链表
阿沁QWQ2 小时前
C语言中的文本读写和二进制读写接口
开发语言·c++·算法
仙人掌_lz2 小时前
深入理解深度Q网络DQN:基于python从零实现
python·算法·强化学习·dqn·rl
小雅痞2 小时前
[Java][Leetcode middle] 80. 删除有序数组中的重复项 II
java·python·leetcode
TsingtaoAI3 小时前
企业内训|智能调控系统算法与优化——某汽车厂商
算法·汽车·ai企业内训·自动驾驶企业内训·智驾企业培训
安特尼3 小时前
招行数字金融挑战赛数据分析赛带赛题二
python·算法·机器学习·金融·数据分析