贪心第二周总结

贪心算法题目中的动态规划暂时先不理解。

无非看脑子灵不灵活

一:力扣:122.买卖股票的最佳时机II

解析:
最终股票可以分为每天股票的和。每天股票都是正值,最终股票最大。
例:第二天买入,第五天卖出去。
prices[5]-prices[2] = -prices[2]+prices[3]-prices[3]+prices[4]-prices[4]+prices[5]
-prices[2]+prices[3]:可理解为第二天的利润。
那么总体看来就是第2,3,4天的利润和。
每天股票都是正值,最终股票最大。

题目:
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

代码:

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

二:
力扣:55. 跳跃游戏
其实跳几步无所谓,关键在于可跳的覆盖范围!那么这个问题就转化为全部覆盖范围究竟可不可以覆盖整个数组!
贪心算法局部最优解:每次取最大跳跃步数(取最大覆盖范围),整体最优解:最后得到整体最大覆盖范围,看是否能到终点。
不是跳跃函数即中间有点是不被覆盖的。那么在所有点中排除掉所有被覆盖的点,看是否有剩余的点即可。若有则说明没有不是跳跃函数。

力扣:
题目:
给你一个非负整数数组 nums ,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
假设你总是可以到达数组的最后一个位置。

前提条件是:假设你总是可以到达数组的最后一个位置。那么此时你只需要研究怎么样才能跳跃次数最少。->贪婪

贪心算法步骤:
1:需要完成的任务
2:将完成任务的整个过程分为几步
3:每一步都很贪
当前位置应该跳到范围内的哪个位置(此位置的范围最大),

1:蹦跳着到达终点且蹦跶次数最少。
2:从下标为0的位置蹦跶到哪个位置,下个位置又蹦跶到哪个位置,直到到达终点。
3:次数最少->贪婪:蹦跶到的下个位置的范围最大然后就可以写代码了。

边界的个数即跳跃次数

C++vector求和,A为vector:

static bool cmp(int a, int b) {
    return abs(a) > abs(b);
}
for (int a : A) result += a;        // 第四步

自己代码:

class Solution {
/*
首先递增排序,然后遍历数组如果是负值的话则取反,此时没有负数了,但是取反还没有完毕。
当次序为偶数则return add,当次序为奇数则将数组排序同时将第一个值取反然后return add
*/
public:
    int largestSumAfterKNegations(vector<int>& nums, int k) {
        sort(nums.begin(),nums.end());
        for (int i = 0, j = 0; j < k; j++) {
            if (nums[i] <= 0) nums[i] = -nums[i];
            else {
                if((k-j) %2 == 0) {
                    return accumulate(nums.begin(), nums.end(), 0);
                }
                else {
                    sort(nums.begin(),nums.end());
                    nums[0] = -nums[0];
                    return accumulate(nums.begin(), nums.end(), 0);
                }
            }
            if(i == nums.size()-1) {
                sort(nums.begin(),nums.end());
                i = 0;
            }
            else {
                i++;
            }
        }
        return accumulate(nums.begin(), nums.end(), 0);
    }
};

别人代码:
那么本题的解题步骤为:
第一步:将数组按照绝对值大小从大到小排序,注意要按照绝对值的大小
第二步:从前向后遍历,遇到负数将其变为正数,同时K–
第三步:如果K还大于0,那么反复转变数值最小的元素,将K用完
第四步:求和

class Solution {
static bool cmp(int a, int b) {
    return abs(a) > abs(b);
}
public:
    int largestSumAfterKNegations(vector<int>& A, int K) {
        sort(A.begin(), A.end(), cmp);       // 第一步
        for (int i = 0; i < A.size(); i++) { // 第二步
            if (A[i] < 0 && K > 0) {
                A[i] *= -1;
                K--;
            }
        }
        if (K % 2 == 1) A[A.size() - 1] *= -1; // 第三步
        int result = 0;
        for (int a : A) result += a;        // 第四步
        return result;
    }
};

区别在于:
1:vector求和
2:非遍历整个数组,而是先把负数处理完。
3:按照绝对值的大小排序此时的好处就是当将数组中的元素全部转换为正数后,K还大于0然后看剩余次数是否为奇数,若为奇数则第一个值直接取反。我的方法此时还要先排序然后在第一个值取反。然后return sum 若为偶数则直接sum。
4:当修改次数大于数组长度还需要处理

不论是做题目还是写block首先分析所有可能情况

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值