海南中小企业网站建设,展厅设计公司网站,建设营销型网站多少钱,做网站买那种服务器好1K 次取反后最大化的数组和
给你一个整数数组 nums 和一个整数 k #xff0c;按以下方法修改该数组#xff1a;
选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。
重复这个过程恰好 k 次。可以多次选择同一个下标 i 。
以这种方式修改数组后#xff0c;返回数组 可能的最…1K 次取反后最大化的数组和
给你一个整数数组 nums 和一个整数 k 按以下方法修改该数组
选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。
重复这个过程恰好 k 次。可以多次选择同一个下标 i 。
以这种方式修改数组后返回数组 可能的最大和 。 示例 1
输入nums [4,2,3], k 1
输出5
解释选择下标 1 nums 变为 [4,-2,3] 。示例 2
输入nums [3,-1,0,2], k 3
输出6
解释选择下标 (1, 2, 2) nums 变为 [3,1,0,2] 。示例 3
输入nums [2,-3,-1,5,-4], k 2
输出13
解释选择下标 (1, 4) nums 变为 [2,3,-1,5,4] 。提示
1 nums.length 104-100 nums[i] 1001 k 104
思路贪心的思路局部最优让绝对值大的负数变为正数当前数值达到最大整体最优整个数组和达到最大。 按绝对值排序为了使得取反操作后的总和最大化应该首先取反绝对值最大的负数因为这样做可以显著增加总和。 贪心策略取反按照元素绝对值的大小对数组进行降序排序这样可以确保先处理绝对值大的负数。 取反过程 遍历排序后的数组依次对负数进行取反操作直到完成 ( k ) 次取反或者没有负数可取反为止。 最后的调整 如果完成了所有的 ( k ) 次取反操作后仍然有剩余的取反次数如果 ( k ) 是奇数则对绝对值最小的元素再进行一次取反操作以进一步增加总和。 计算总和计算修改后数组的总和即为最终的结果。
代码
class Solution {// 比较函数用于排序按绝对值大小排序static bool cmp(int a, int b) {return abs(a) abs(b);}
public:// 计算将数组中的元素进行 k 次取反后能得到的最大和int largestSumAfterKNegations(std::vectorint nums, int k) {// 将数组按绝对值大小排序sort(nums.begin(), nums.end(), cmp);// 遍历数组将负数取反 k 次for (int i 0; i nums.size(); i) {// 如果当前元素为负数且还有剩余的取反次数if (nums[i] 0 k 0) {nums[i] nums[i] * -1; // 取反k--; // 取反次数减少}}// 如果 k 仍然是奇数则将数组中绝对值最小的元素再取反一次if (k % 2 1) nums[nums.size() - 1] * -1;// 计算取反后数组的和int result 0;for (int i 0; i nums.size(); i) {result nums[i];}return result;}
};
2加油站
在一条环路上有 n 个加油站其中第 i 个加油站有汽油 gas[i] 升。
你有一辆油箱容量无限的的汽车从第 i 个加油站开往第 i1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发开始时油箱为空。
给定两个整数数组 gas 和 cost 如果你可以按顺序绕环路行驶一周则返回出发时加油站的编号否则返回 -1 。如果存在解则 保证 它是 唯一 的。 示例 1:
输入: gas [1,2,3,4,5], cost [3,4,5,1,2]
输出: 3
解释:
从 3 号加油站(索引为 3 处)出发可获得 4 升汽油。此时油箱有 0 4 4 升汽油
开往 4 号加油站此时油箱有 4 - 1 5 8 升汽油
开往 0 号加油站此时油箱有 8 - 2 1 7 升汽油
开往 1 号加油站此时油箱有 7 - 3 2 6 升汽油
开往 2 号加油站此时油箱有 6 - 4 3 5 升汽油
开往 3 号加油站你需要消耗 5 升汽油正好足够你返回到 3 号加油站。
因此3 可为起始索引。
示例 2:
输入: gas [2,3,4], cost [3,4,3]
输出: -1
解释:
你不能从 0 号或 1 号加油站出发因为没有足够的汽油可以让你行驶到下一个加油站。
我们从 2 号加油站出发可以获得 4 升汽油。 此时油箱有 0 4 4 升汽油
开往 0 号加油站此时油箱有 4 - 3 2 3 升汽油
开往 1 号加油站此时油箱有 3 - 3 3 3 升汽油
你无法返回 2 号加油站因为返程需要消耗 4 升汽油但是你的油箱只有 3 升汽油。
因此无论怎样你都不可能绕环路行驶一周。 提示:
gas.length ncost.length n1 n 1050 gas[i], cost[i] 104
思路那么局部最优当前累加和curSum一旦小于0起始位置至少要是i1因为从i之前开始一定不行。全局最优找到可以跑一圈的起始位置。 局部最优性从每个加油站出发计算到下一个加油站的剩余油量gas[i] - cost[i]并累加到 curSum 中。同时也将这个值累加到 totalSum 中用于判断是否存在一条路径使得环绕行驶是可能的。 重置起始站点如果 curSum 变成负数意味着当前的起始站点无法到达当前加油站因此将起始站点更新为下一个加油站并将 curSum 重置为 0。 总体可行性在遍历完所有加油站后如果 totalSum 小于 0则表示无法从任何一个加油站出发绕一圈行驶。 返回起始站点如果 totalSum 大于等于 0则返回最初设定的起始站点。
代码
class Solution {
public:// 判断能否环绕行驶一圈并返回起始站点int canCompleteCircuit(std::vectorint gas, std::vectorint cost) {int curSum 0; // 当前剩余的油量int totalSum 0; // 总剩余油量int start 0; // 起始站点// 遍历所有站点for (int i 0; i gas.size(); i) {// 计算当前站点剩余的油量curSum gas[i] - cost[i];// 计算总剩余油量totalSum gas[i] - cost[i];// 如果当前剩余油量小于0if (curSum 0) {// 将起始站点更新为下一站start i 1;// 重置当前剩余油量为0curSum 0;}}// 如果总剩余油量小于0表示无法完成环绕行驶一圈if (totalSum 0) return -1;// 返回起始站点return start;}
};
3 分发糖果
n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。
你需要按照以下要求给这些孩子分发糖果
每个孩子至少分配到 1 个糖果。相邻两个孩子评分更高的孩子会获得更多的糖果。
请你给每个孩子分发糖果计算并返回需要准备的 最少糖果数目 。 示例 1
输入ratings [1,0,2]
输出5
解释你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。示例 2
输入ratings [1,2,2]
输出4
解释你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。第三个孩子只得到 1 颗糖果这满足题面中的两个条件。 提示
n ratings.length1 n 2 * 1040 ratings[i] 2 * 104
思路 初始化糖果分配首先初始化一个糖果数组 candymum所有孩子初始分配一个糖果。 从左到右遍历 遍历孩子列表从左到右比较相邻孩子的评分。如果当前孩子的评分高于前一个孩子的评分则给当前孩子多分配一颗糖果至少比前一个多一颗。从右到左遍历 由于评分高的孩子不一定只比左边孩子评分高还可能比右边孩子评分高所以需要再次遍历。从右到左遍历孩子列表比较相邻孩子的评分。如果当前孩子的评分高于右边孩子的评分并且当前孩子已分配的糖果数不多于右边孩子违反了规则则给当前孩子增加糖果数量直到满足条件。 计算总糖果数量遍历糖果数组计算总共分发的糖果数量。 返回结果返回总糖果数量作为最终结果。 代码
class Solution {
public:int candy(vectorint ratings) {// 初始化每个孩子分得的糖果数量为1vectorint candymum(ratings.size(), 1);// 从左到右遍历如果右边的孩子比左边的孩子评分高则糖果数量加1for(int i 1; i ratings.size(); i){if (ratings[i] ratings[i - 1]) candymum[i] candymum[i - 1] 1;}// 从右到左遍历如果左边的孩子比右边的孩子评分高并且左边孩子的糖果数量不比右边多则更新糖果数量为右边糖果数量加1for (int i ratings.size() - 2; i 0; i--) {if (ratings[i] ratings[i 1] ) {candymum[i] max(candymum[i], candymum[i 1] 1);}}// 计算总共分发的糖果数量int result 0;for(int i 0; i candymum.size(); i) result candymum[i];return result;}
};