1005.K次取反后最大化的数组和
var largestSumAfterKNegations = function(nums, k) {
while(k>0){
nums.sort((a,b)=>a-b);
nums[0]=-nums[0];
k--
}
return nums.reduce((prev, cur)=>prev+cur,0)
};
第一想法
每次换最小的那个数,负数换正数,正数换负数,对加起来最大都是最好的选择。但是我用的是sort,应该有更好的方法。
卡哥的思想
先把绝对值大的负数转换了。如果全是正数了,转换最小的那个正数
第一步:将数组按照绝对值大小从大到小排序,注意要按照绝对值的大小
第二步:从前向后遍历,遇到负数将其变为正数,同时K–
第三步:如果K还大于0,那么反复转变数值最小的元素,将K用完
第四步:求和
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var largestSumAfterKNegations = function (nums, k) {
nums.sort((a, b) => Math.abs(b) - Math.abs(a)); // 按绝对值排序
let sum=0
for(let i = 0; i < nums.length; i++) {
if(nums[i] < 0 && k-- > 0) { // 负数取反(k 数量足够时)
nums[i] = -nums[i];
}
sum+=nums[i]
}
if(k>0&&k%2)
sum-=2*nums[nums.length - 1]
return sum
};
134. 加油站
var canCompleteCircuit = function (gas, cost) {
let ok = [];
let i = 0;
let count = gas.length;
if (count === 1 && gas[i] === cost[i]) {
return 0;
}
while (i < gas.length) {
if (gas[i] > cost[i]) ok.push(i);
i++;
}
for (let i = 0; i < ok.length; i++) {
let c = ok[i];
let sum = gas[c];
let d = 0;
while (d < count - 1 && sum >= cost[c]) {
sum = sum - cost[c] + gas[(c + 1) % count];
if (sum < 0) break;
d++;
c = (c + 1) % count;
}
if (sum > 0) sum -= cost[c % count];
if (sum >= 0) return ok[i];
}
return -1;
};
第一想法
按这个来
卡哥的
首先如果总油量减去总消耗大于等于零那么一定可以跑完一圈,说明 各个站点的加油站 剩油量rest[i]相加一定是大于等于零的。
每个加油站的剩余量rest[i]为gas[i] - cost[i]。
i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i]区间都不能作为起始位置,因为这个区间选择任何一个位置作为起点,到i这里都会断油,那么起始位置从i+1算起,再从0计算curSum。
如图:
135. 分发糖果
/**
* @param {number[]} ratings
* @return {number}
*/
var candy = function(ratings) {
let n=ratings.length
let ok=new Array(n)
ok.fill(1);
for(let i=0;i<n-1;i++){
//->
if(ratings[i]<ratings[i+1])
ok[i+1]=ok[i]+1
}
for(let i=n-1;i>0;i--){
if(ratings[i]<ratings[i-1]){
ok[i-1]=ok[i-1]>ok[i]+1?ok[i-1]:ok[i]+1
}}
let sum=0
for(let i=0;i<n;i++){
sum+=ok[i]
}
return sum }