贪心思想

1. 分配饼干   难度:easy   Leetcode题号:455

题目描述:

思路:贪心思想,即将饼干大小和孩子的胃口大小分别排序,将较小的饼干优先分配给胃口较小的孩子,这样才能用较大的饼干尽可能去满足胃口较大的孩子

代码如下:

class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        sort(g.begin(), g.end());
        sort(s.begin(), s.end());
        int res = 0;
        int i = 0 , j = 0;
        while( i < g.size() && j < s.size()){
            if(s[j] >= g[i]){
                res++;//满足了一个孩子
                i++;
            } 
            j++;
        }
        return res;
    }
};

2. 无重叠区间  难度:medium   Leetcode题目号:435

题目描述:

思路:

要求可去掉的区间的最小值,可先求出无重叠区间个数的最大值unoverlap_interval,然后用总区间个数减去unoverlap_interval,

即为所求

无重叠区间最大个数可用贪心算法进行求解,即:

先按区间末尾值对区间进行升序排序,当区间末尾值相同时,优先选择区间长度短的,即起始值大的;这样就能保证之后留有更多的空间去容纳尽可能多的区间,之后放置区间时,选择和前一个被选中的区间不重叠的

C++代码如下:

class Solution {
public:
    static bool cmp(vector<int> &a, vector<int> &b){
        if(a[1]<b[1]){
            return true;
        } else if(a[1]==b[1]){
            return a[0]>b[0];
        }
        return false;
    }
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        if(intervals.size()==0){
            return 0;
        }
        sort(intervals.begin(),intervals.end(),cmp);//根据区间末尾进行排序
        int unoverlap_interval=1;//未重叠的最大区间数,先把排序后的第一个区间记入
        int last=intervals[0][1];//未重叠的上个区间的末尾
        for(int i=1;i<intervals.size();i++){
            if(intervals[i][0]>=last){
                unoverlap_interval++;
                last=intervals[i][1];
            }
        }
        int res=intervals.size()-unoverlap_interval;//所有区间数目减去未重叠区间最大数目为答案
        return res;
    }
};

3. 用最少数量的箭引爆气球    难度:medium    Leetcode题号:452

题目描述:

思路:

此题与上一题目几乎一样,区别就在于此题求的就是不重叠区间的数目,且[1,2]与[2,3]这种算作是重叠的区间(因为一支箭可以将二者同时引爆)

代码如下:

bool cmp(vector<int> &a, vector<int> &b){
    return a[1]<b[1] || (a[1]==b[1] && a[0]>b[0]);
}
class Solution {
public:
    int findMinArrowShots(vector<vector<int>>& points) {
        if(points.size() == 0){
            return 0;
        }
        sort(points.begin(), points.end(), cmp);
        int res = 1;//不重叠区间的个数
        int last = points[0][1];
        for(int i = 0; i < points.size(); i++){
            if(points[i][0] > last){
                res++;
                last = points[i][1];
            }
        }
        return res;
    }
};

4. 根据身高重建队列   难度:medium   Leetcode题号:406

题目描述:

主要突破口:当一群人的身高都一致时,他们应站在的位置就是k值,比如[5,0],[5,1]和[5,2]应依次排列

思路:首先将人群按照身高h进行降序排列,再按前面大于等于自己身高的人数k进行升序排列

先将身高较高且身高一致的人按照k值去安排位置,之后的身高一致的一批人也按照k值去插入其中,由于插入的人的身高总是比原来已安排好的人的身高矮,故插入后不会影响往后挪一个位置的那个人k值与顺序的对应关系

代码如下:

bool cmp(vector<int> &a, vector<int> &b){
    return a[0]>b[0] || (a[0]==b[0] && a[1]<b[1]);
}
class Solution {
public:
    vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        sort(people.begin(), people.end(), cmp);
        vector<vector<int>> ans;
        for(int i=0;i<people.size();i++){
            ans.insert(ans.begin()+people[i][1], {people[i][0], people[i][1]});
        }
        return ans;
    }
};

5. 买卖股票的最佳时机  难度:easy   Leetcode题号:121

题目描述:

思路:记录前面几天的最小价格,每到新的一天都算一下今天卖出的利润,比较一下,若比之前的利润大就更新一下利润,最后得到的就是最大利润

代码:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if(prices.size()==0){
            return 0;
        }
        int n=prices.size();
        int Min=INT_MAX;
        int ans=0;//利润 
        for(int i=0;i<n;i++){
            if(prices[i]<Min){
                Min=prices[i];
            } else{
               ans=max(ans,prices[i]-Min);//今天卖出是不是比之前的最大利润大
            }
        }
        return ans;
    }
};

 

6. 买卖股票的最佳时机II   难度:easy    Leetcode题号:122

题目描述:

思路:

贪心:比如a<x<b,由于有b-a=(b-x)+(x-a),故只要后一天比前一天价格高,就将股票卖出,最后得到的一定是最大利润

C++代码如下:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int ans = 0;
        for(int i=1;i<prices.size();i++){
            if(prices[i]>prices[i-1]){
                ans += prices[i]-prices[i-1];
            }
        }
        return ans;
    }
};

 

7. 种花问题   难度:easy    Leetcode题号:605

题目描述:

思路:设置一个计数器count,记录还能种花的位置的最大数量,当其前后位置都没有花时(第一个位置和最后一个位置需单独考虑),就种一朵花,若最后count>=n,则表明还可以种上n朵花,否则不能

代码:

class Solution {
public:
    bool canPlaceFlowers(vector<int>& flowerbed, int n) {
        int count = 0;
        int len = flowerbed.size();
        for(int i = 0; i < len && count <= n; i++){
            if(flowerbed[i] == 1){
                continue;
            }
            int pre = i == 0 ? 0 : flowerbed[i-1];
            int next = i == len - 1 ? 0 : flowerbed[i+1];
            if(pre == 0 && next == 0){
                count++;
                flowerbed[i] = 1;
            }
        }
        return count >= n; 
    }
};

 

8. 判断子序列   难度:easy    Leetcode题号:392

题目描述:

思路:双指针+贪心,i指向s串,j指向t串,只考虑s[i]和t[j]是否相等,若s[i]==t[j],两者同时动,否则只有j动,只要能在后面找到它就可以

代码:

class Solution {
public:
    bool isSubsequence(string s, string t) {
        int i = 0, j = 0;
        int count = 0;
        while(i < s.size() && j < t.size()){
            if(s[i] == t[j]){
                count++;
                i++;
            } 
            j++;
        }
        return count == s.size();
    }
};

 

9. 非递减数列   难度:easy   Leetcode题号:665

题目描述:

思路:

当数组中出现nums[i] < nums[i-1] 的情况时,应考虑修改哪个数,能够使得i之前位置的数组成一个非递减数列,并不影响后续操作(即贪心,只考虑眼下最优的),显然应该令nums[i-1] = nums[i],因为若令nums[i] = nums[i-1],则i位置的值变大了,有可能比nums[i+1]大,而影响了后续操作。还有一种特殊的情况:nums[i] < nums[i-2],这种情况下若令nums[i-1] = nums[i],则仍不满足非递减数列,故这时只能令nums[i] = nums[i-1]

代码如下:

class Solution {
public:
    bool checkPossibility(vector<int>& nums) {
        int count = 0;
        for(int i = 1; i < nums.size() && count <= 1; i++){
            if(nums[i] >= nums[i-1]){
                continue;
            }
            count++;
            if(i-2 >= 0 && nums[i] < nums[i-2]){
                nums[i] = nums[i-1];
            } else{
                nums[i-1] = nums[i];
            }
        }
        return count <= 1;
    }
};

 

10. 最大子序列和   难度:easy   Leetcode题号: 53

题目描述:

思路:

使用一个pre_sum变量记录到当前数的最大子序和,一个max_sum变量记录真正的最大子序和,若考虑nums[i]和pre_sum+nums[i]的大小,去二者的较大值,然后比较pre_sum和max_sum的值,更新max_sum的值

代码如下:

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        if(nums.size()==0){
            return 0;
        }
        int n=nums.size();
        int pre_sum = nums[0];
        int max_sum = pre_sum;
        for(int i=1;i<n;i++){
            pre_sum = pre_sum > 0 ? pre_sum + nums[i] : nums[i];
            max_sum = max(max_sum, pre_sum);
        }
        return max_sum;
    }
};

 

11. 划分字母区间  难度:medium   Leetcode题号:763

题目描述:

代码:

class Solution {
public:
    vector<int> partitionLabels(string S) {
        vector<int> res;
        map<char,int> Map;
        int start = 0, end = 0; 
        for(int i = 0; i < S.size(); i++){
            Map[S[i]] = i; //记录每个字母的最大下标
        }
        for(int i = 0 ; i < S.size(); i++){
            end = max(end, Map[S[i]]);//若当前字母的最大下标大于end,则将end拓展
            if(i == end){
                res.push_back(end - start + 1);
                start = i + 1;//开始搜索下一个片段
            }
        }
        return res;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值