代码随想录算法训练营第二十八天| 1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果
1005.K次取反后最大化的数组和
思路:
仅排序一次,当前数<下一个数,就反转当前数,如果大于,那么就反转下一个 ——》也就是保证每次反转都是最小的数
注意:如果移动到最后一个节点了,K还没用完,那么就证明只能反转K
代码:
1 int largestSumAfterKNegations(vector<int>& nums, int k) { 2 if (nums.size() == 0) return 0; 3 sort(nums.begin(), nums.end()); 4 5 int i = 0; 6 //可能存在最后一个数为最小数 7 while ( k > 0) 8 { 9 //如果到最后一个数了,K还没用完,就证明只能修改最后一个数 10 if (i == nums.size() - 1) 11 { 12 nums[i] = -nums[i]; 13 k--; 14 continue; 15 } 16 //这个只能保证当前数是不是小数, 17 if (i < nums.size() - 1 && nums[i] <= nums[i + 1]) 18 { 19 nums[i] = -nums[i]; 20 k--; 21 } 22 else 23 { 24 i++; 25 } 26 27 } 28 29 int result = 0; 30 for (int j = 0; j < nums.size(); j++) 31 { 32 result += nums[j]; 33 } 34 35 return result; 36 }
134. 加油站
难点:
1,是一个循环
2,初始节点是任意的
思路:
1,如果全部差和<0,则证明跑步玩一圈,直接返回-1
2,如果累加过程中,出现了负数,则证明不可行,从下一节点开始,直到找到一个节点,累加过程中不会出现负数
代码:
1 int canCompleteCircuit(vector<int>& gas, vector<int>& cost) { 2 int result = 0; 3 int totalSum = 0; 4 int curSum = 0; 5 for (int i = 0; i < gas.size(); i++) 6 { 7 int cur = gas[i] - cost[i]; 8 totalSum += cur; 9 curSum += cur; 10 if (curSum < 0) 11 { 12 curSum = 0; 13 result = i + 1; 14 } 15 } 16 17 if (totalSum < 0) return -1; 18 return result; 19 }
135. 分发糖果
难点:
如何保证他是动态更新的,因为如果当前节点大于临边的时候,修改过后,之前的节点很难跟着更改
正确的做法:
从左到右 然后从右到左,切记不能两次都从左到右
不能比较即将更改的数据上进行更改
代码:
1 int candy(vector<int>& ratings) { 2 vector<int> child(ratings.size(), 1); 3 4 // 从左到右 5 for (int i = 1; i < ratings.size(); i++) 6 { 7 if (ratings[i] > ratings[i - 1]) 8 { 9 child[i] = child[i - 1] + 1; 10 } 11 } 12 13 //从右到左 14 for (int i = ratings.size() - 2; i >= 0; i--) 15 { 16 if (ratings[i] > ratings[i + 1]) 17 { 18 int cur = child[i + 1] + 1; 19 child[i] = max(child[i], cur); 20 } 21 } 22 23 int result = 0; 24 for (int i = 0; i < child.size(); i++) 25 { 26 result += child[i]; 27 } 28 29 return result; 30 }