LeetCode刷题笔记【25】:贪心算法专题-3(K次取反后最大化的数组和、加油站、分发糖果)

这篇具有很好参考价值的文章主要介绍了LeetCode刷题笔记【25】:贪心算法专题-3(K次取反后最大化的数组和、加油站、分发糖果)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前置知识

参考前文

参考文章:
LeetCode刷题笔记【23】:贪心算法专题-1(分发饼干、摆动序列、最大子序和)
LeetCode刷题笔记【24】:贪心算法专题-2(买卖股票的最佳时机II、跳跃游戏、跳跃游戏II)

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

题目描述

LeetCode刷题笔记【25】:贪心算法专题-3(K次取反后最大化的数组和、加油站、分发糖果),LeetCode刷题笔记,leetcode,笔记,贪心算法,算法,c++

LeetCode链接:https://leetcode.cn/problems/maximize-sum-of-array-after-k-negations/description/

分情况讨论

首先sort nums, 然后统计其中的负数的数量为n
n=k, 将所有负数转为正数
n>k, 从小到大地处理k个负数, 然后结束
n<k, 将所有负数转为正数后, 再sort数组, 对sort后的数组最小数处理(k-n)

class Solution {
public:
    int largestSumAfterKNegations(vector<int>& nums, int k) {
        sort(nums.begin(), nums.end());
        int n=0;
        for(int num : nums){
            if(num<0)
                n++;
            else
                break;
        }
        if(n>=k){
            for(int i=0; i<k; i++){
                nums[i] = -nums[i];
            }
        }else{
            for(int i=0; i<n; i++){
                nums[i] = -nums[i];
            }
            sort(nums.begin(), nums.end());
            int key = k-n;
            if(key%2 != 0)
                nums[0] = -nums[0];
        }
        int ans=0;
        for(int num : nums){
            ans += num;
        }
        return ans;
    }
};

贪心算法

换一种实现方法: 先按照绝对值进行从大到小排序, 然后遍历加和
k没用完的时候遇到负数就加上其绝对值, k--
k用完了就加上其本身值, 遍历到最后如果k还有剩余, 且剩余k为奇数, 就加上最后一个数的负数

class Solution {
public:
    int largestSumAfterKNegations(vector<int>& nums, int k) {
        sort(nums.begin(), nums.end(), [](int a, int b){
            return abs(a)>abs(b);
        });
        int ans=0;
        for(int i=0; i<nums.size(); ++i){
            if(nums[i]<0 && k>0){
                nums[i] = -nums[i];
                k--;
            }
        }
        if(k%2==1)
            nums.back() = -nums.back();
        for(int num : nums)
            ans += num;
        return ans;
    }
};

134. 加油站

题目描述

LeetCode刷题笔记【25】:贪心算法专题-3(K次取反后最大化的数组和、加油站、分发糖果),LeetCode刷题笔记,leetcode,笔记,贪心算法,算法,c++

LeetCode链接:https://leetcode.cn/problems/gas-station/description/

暴力解法

① 暴力解法, 把每个点都尝试跑一遍

class Solution {
public:
    bool check(int index, vector<int>& diff){
        int sum=diff[index], cur=index+1;
        if(cur>=diff.size())
            cur=0;
        while(cur != index){
            if(sum<0){
                return false;
            }else{
                sum += diff[cur];
                cur ++;
                if(cur>=diff.size())
                    cur=0;
            }
        }
        if(sum<0)
            return false;
        return true;
    }
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int n=gas.size();
        vector<int> diff(n);
        for(int i=0; i<n; ++i){
            diff[i] = gas[i] - cost[i];
        }
        for(int i=0; i<n; ++i){
            if(check(i, diff))
                return i;
        }
        return -1;
    }
};

贪心算法

很遗憾, 暴力解法超出时间限制了
② 贪心算法, 过程中维护curSumtotalSum;
curSum<0时整个计数从i+1开始(curSum置为0)(将ans置为i+1)
totalSum记录所有的sum, 如果最后totalSum<0, 那么返回-1

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int ans=0;
        int curSum=0;
        int totalSum=0;
        for(int i=0; i<gas.size(); ++i){
            totalSum += gas[i]-cost[i];
            curSum += gas[i]-cost[i];
            if(curSum<0){
                ans = i+1;
                curSum = 0;
            }
        }
        if(totalSum<0)
            return -1;
        return ans;
    }
};

135. 分发糖果

题目描述

LeetCode刷题笔记【25】:贪心算法专题-3(K次取反后最大化的数组和、加油站、分发糖果),LeetCode刷题笔记,leetcode,笔记,贪心算法,算法,c++

LeetCode链接:https://leetcode.cn/problems/candy/description/

暴力解法

暴力解法: 创建vector<int> candy(ratings.size(), 1), 记录给每个孩子分的糖, 初始每个孩子都有一颗糖
多次遍历, 发现一个孩子比相邻的孩子ratings高, 但是candy没有更多, 就candy++, 同时ans++
循环遍历, 直到没有发现以上情况

class Solution {
public:
    bool check(int i, vector<int>& ratings, vector<int>& candy){
        if(i==0){
            if(ratings[i]>ratings[i+1] && candy[i]<=candy[i+1])
                return true;
            else
                return false;
        }else if(i==ratings.size()-1){
            if(ratings[i]>ratings[i-1] && candy[i]<=candy[i-1])
                return true;
            else
                return false;
        }else{
            if((ratings[i]>ratings[i+1] && candy[i]<=candy[i+1]) || (ratings[i]>ratings[i-1] && candy[i]<=candy[i-1]))
                return true;
            else
                return false;
        }
        return false;
    }
    int candy(vector<int>& ratings) {
        vector<int> candy(ratings.size(), 1);
        int ans=ratings.size();
        if(ans<=1)
            return ans;
        bool changed=true;
        while(changed==true){
            changed = false;
            for(int i=0; i<ratings.size(); ++i){
                if(check(i, ratings, candy)){
                    candy[i] ++;
                    changed = true;
                    ans ++;
                }
            }
        }
        return ans;
    }
};

贪心算法

很遗憾, 通过样例, 但是超出时间范围
参考<代>, 使用贪心算法, 具体操作如下
进行两次遍历, 一次从前往后, 一次从后往前
从前往后遍历过程中: 如果发现ratings[i+1]>ratings[i], 则candy[i+1] = max(candy[i+1], candy[i]+1);
从后往前遍历过程中: 如果发现ratings[i-1]>ratings[i], 则candy[i-1] = max(candy[i-1], candy[i]+1);

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

总结

贪心, 讲真就是只有思想, 没有固定的套路.
现在做(被折磨)多了, 下意识的, 逐渐有一种"看看了解了解"的想法了.

如果笔试的时候真遇到类似的题目, 如果可以想到贪心, 那么最好;
如果一时半会儿没有想到很巧妙的方法, 最好先用暴力解法, 通过一部分测试用例, 分到手最好.

归根到底还是要代码实现能力过硬, 可不要感觉暴力解法是那么简单哦~
很多时候想的很清楚, 写出来就是很奇怪;

并且写的是一会儿, 往往在代码层面可以有优化很多的写法.
当然, 这样的功夫, 也只能在不断的练习过程中慢慢培养了.

本文参考:
K次取反后最大化的数组和
加油站
分发糖果文章来源地址https://www.toymoban.com/news/detail-700731.html

到了这里,关于LeetCode刷题笔记【25】:贪心算法专题-3(K次取反后最大化的数组和、加油站、分发糖果)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 贪心算法|1005.K次取反后最大化的数组和

    力扣题目链接 有没有不理解的语法知识呢? sort函数中的比较函数cmp(),即 void sort( iterator start, iterator end, StrictWeakOrdering cmp ); sort函数头文件为: #include algorithm 其中,cmp函数可以自己编写,自己决定逻辑,包括cmp的命名也是自己决定的。 示例如下:  代码随想录 (programmerc

    2024年04月09日
    浏览(50)
  • DAY38:贪心算法(五)K次取反后最大数组和+加油站

    本题重点是逻辑问题,同时复习static和sort的自定义操作与时间复杂度 给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组: 选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。 重复这个过程恰好 k 次。可以多次选择同一个下标 i 。 以这种方式修改数组后,返回数组 可能的

    2024年02月13日
    浏览(29)
  • LeetCode刷题笔记【26】:贪心算法专题-4(柠檬水找零、根据身高重建队列、用最少数量的箭引爆气球)

    参考前文 参考文章: LeetCode刷题笔记【23】:贪心算法专题-1(分发饼干、摆动序列、最大子序和) LeetCode刷题笔记【24】:贪心算法专题-2(买卖股票的最佳时机II、跳跃游戏、跳跃游戏II) LeetCode刷题笔记【25】:贪心算法专题-3(K次取反后最大化的数组和、加油站、分发糖

    2024年02月09日
    浏览(31)
  • 算法 贪心3 || 1005. K 次取反后最大化的数组和 134. 加油站 135. 分发糖果

    思路: 给数组按照绝对值大小排序 ,优先将负数转成正数。如果此时 k % 2 == 1 。最后再将 绝对值最小的值变成负数 (该值可能原本是负数) 而不是直接从小到大排序。 例如-8,-5,-5,-3,-2,9这种序列。如果直接从小到大排序,那么最后一个变符号的就会是9,但其实让

    2023年04月12日
    浏览(23)
  • 【贪心算法Part03】| 1005.K次取反后最大化的数组和、134.加油站、135.分发糖果

    目录 🎈LeetCode1005.K次取反后最大化的数组和  🎈LeetCode134.加油站 🎈LeetCode135.分发糖果 链接:1005.K次取反后最大化的数组和 给你一个整数数组  nums  和一个整数  k  ,按以下方法修改该数组: 选择某个下标  i  并将  nums[i]  替换为  -nums[i]  。 重复这个过程恰好  k  次

    2024年02月16日
    浏览(31)
  • Day34 贪心算法 part03 1005. K 次取反后最大化的数组和 134. 加油站 135. 分发糖果

    思路 第一步,从前向后遍历,遇到负数将其变为正数,同时K– 第二步:如果K还大于0,那么反复转变数值最小的元素,将K用完 第三步:求和 方法一(暴力) leetcode超时(35/40) 方法二(贪心)

    2024年01月19日
    浏览(31)
  • 第八章 贪心算法 part03 1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果 (day34补)

    给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组: 选择某个下标 i  并将 nums[i] 替换为 -nums[i] 。 重复这个过程恰好 k 次。可以多次选择同一个下标 i 。 以这种方式修改数组后,返回数组 可能的最大和 。 示例 1: 示例 2: 示例 3: 提示: 1 = nums.length = 104 -100

    2024年02月11日
    浏览(22)
  • 【Leetcode60天带刷】day33回溯算法——1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果

    ​ 1005. K 次取反后最大化的数组和 给你一个整数数组  nums  和一个整数  k  ,按以下方法修改该数组: 选择某个下标  i  并将  nums[i]  替换为  -nums[i]  。 重复这个过程恰好  k  次。可以多次选择同一个下标  i  。 以这种方式修改数组后,返回数组  可能的最大和  。

    2024年02月11日
    浏览(25)
  • 【贪心算法】leetcode刷题

    贪心算法无固定套路。 核心思想:先找局部最优,再扩展到全局最优。 两种思路: 1、从大到小。局部最优就是大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩。 先遍历的胃口,在遍历的饼干 2、从小到大。 小饼干先喂饱小胃口 。两个

    2024年02月14日
    浏览(30)
  • LeetCode刷题笔记【30】:动态规划专题-2(不同路径、不同路径 II)

    参考前文 参考文章: LeetCode刷题笔记【29】:动态规划专题-1(斐波那契数、爬楼梯、使用最小花费爬楼梯) LeetCode链接:https://leetcode.cn/problems/unique-paths/description/ 动态规划 : 创建m×n的数组, 对应这个地图, 数组 val 表示 有几种方法可以走到这一格 最开始, 第一行和第一列v

    2024年02月09日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包