代码随想录训练营Day33(贪心算法):Leetcode1005、134、135(难得有一天能完全独立做出题目)

Leetcode1005:

题目描述:

给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组:

  • 选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。

重复这个过程恰好 k 次。可以多次选择同一个下标 i 。

以这种方式修改数组后,返回数组 可能的最大和 。

代码及注释:

class Solution {
public:
    int largestSumAfterKNegations(vector<int>& nums, int k) {
        //使用优先队列存储值最小的K个元素
        priority_queue<pair<int, int>>p;
        for (int i = 0; i < nums.size(); i++) {
            //存储值最小,因为默认是大根堆,所以存储负值
            p.push(pair<int, int>(-nums[i], i));
        }

        //对值最小的值取反
        //1.如果存在负数,优先取反最小的负数,可以使得和变大
        //2.不存在负数,但有0值,取反0值可以让数组值和不变
        //3.只存在非负整数,取反最小的值,可以使得代价最小

        //执行k次
        while (!p.empty() && k--) {
            pair<int, int>pp = p.top();
            p.pop();
            //如果只有0和正整数,可以对0取反k次,因此可以直接跳出循环
            if (nums[pp.second] == 0)break;


            else nums[pp.second] = -nums[pp.second];
            pp.first = -pp.first;

            //完成取反,得到新的值,重新加入
            p.push(pp);
        }
        int sum = 0;
        for (int i = 0; i < nums.size(); i++) {
            sum += nums[i];
        }
        return sum;
    }
};

Leetcode134:

题目描述:

在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。

你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。

给定两个整数数组 gas 和 cost ,如果你可以按顺序绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1 。如果存在解,则 保证 它是 唯一 的。

代码及注释:

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {

        int n = gas.size();
        //处理后的gas代表,gas[i]从第i个加油站到达第(i+1)个加油站所增加/减少的油
        for (int i = 0; i < n; i++) {
            gas[i] -= cost[i];
        }

        //由于起点唯一,因此如果存在等于0可以做起点,那只可能是只有一个元素
        if (n == 1 && gas[0] >= 0)return 0;

        //对每个加油站都尝试作为起点
        for (int i = 0; i < n;) {
            //作为起点的加油站必须能到达下一个加油站,本来就是没有油
            //gas[i]为负数,就不可能可以让i作为起点

            //大于0才能作为起点
            if (gas[i] > 0) {
                //记录到达加油站i+1还剩多少油
                int sum = gas[i];
                int begin = i;

                //>=0 才能说明可以到达 i+1
                while (sum >= 0) {
                    //继续向后走
                    i = (i + 1) % n;
                    sum += gas[i];

                    //直到又回到起点,完成搜索
                    if (sum >= 0 && i == begin)return begin;
                }

                //剪枝
                if (i > begin && i < n)continue;

                i = begin + 1;

            }
            else {
                i++;
            }

        }return -1;
    }
};

Leetcode135:

题目描述:

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。

你需要按照以下要求,给这些孩子分发糖果:

  • 每个孩子至少分配到 1 个糖果。
  • 相邻两个孩子评分更高的孩子会获得更多的糖果。

请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。

代码及注释:

class Solution {
public:
    int candy(vector<int>& ratings) {
        int n = ratings.size();
        int* ans = new int[n];

        //第一个孩子先给一个糖果
        ans[0] = 1;

        //边走边发糖果
        for (int i = 1; i < n; i++) {
            //如果当前孩子评分>前一个孩子
            if (ratings[i] > ratings[i - 1]) {
                //比前一个孩子多发一个糖果即可
                ans[i] = ans[i - 1] + 1;
            }
            //如果<=前一个孩子评分
            else {
                //给一个糖果就行
                ans[i] = 1;
                int j = i - 1;

                //前一个孩子也是只有一个糖果&&前一个孩子评分>当前孩子评分
                if (ans[j] == 1 && ratings[j] > ratings[i]) {
                    //i-1孩子多发一个糖果
                    ans[j] += 1;
                    j--;

                    //往前走,回溯
                    while (j >= 0 && ratings[j] > ratings[j + 1] && ans[j] <= ans[j + 1])ans[j] = ans[j + 1] + 1, j--;
                }
            }
        }

        int sum = 0;
        for (int i = 0; i < n; i++) {
            sum += ans[i];
        }
        return sum;
    }
};

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第二十二天的算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值