LeetCode 1005. K次取反后最大化的数组和
题目链接:1005. K 次取反后最大化的数组和 - 力扣(LeetCode)
思路:
题目的要求是求给定数组的最大之和,因此在每次反转的时候我们应该把小于0且尽量小的数给反转了,这样会得到较大的数,如果说还没反转完负数,k次就用完了,直接返回其和;如果所有数组都遍历过了,那么现在都是正数,我们重新排序,对着最小的一个正整数薅羊毛,这样k次不断反转,就算是有一个负数,也是减去最小的一个数得到最大的和。
代码:
#python
class Solution:
def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
nums.sort()
index = 0
while k > 0: //一共反转k次
if nums[index] < 0 and index < len(nums) - 1: 要注意index不能超过数组范围
nums[index] = -nums[index] //把未反转过的负数给反转一下
index += 1 //平移至当前最小的负数
k -= 1
elif nums[index] >= 0 and index < len(nums) - 1:
index += 1 //如果是正数index就继续走
else:
nums.sort() //所有数都是正数了
nums[0] = nums[0] if k % 2 == 0 else -nums[0] //盯着最小数薅羊毛
k = 0 //全部结束了,注意把k赋值为0,跳出循环
return sum(nums) //返回最大之和
/java
class Solution {
public int largestSumAfterKNegations(int[] nums, int k) {
Arrays.sort(nums);
for(int i = 0; i < nums.length; i++){
if(nums[i] < 0 && k > 0){
nums[i] = -nums[i];
k--;
}
else{
break;
}
}
if(k > 0){
Arrays.sort(nums);
if(k % 2 == 1){
nums[0] = -nums[0];
}
}
int res = 0;
for(int i : nums){
res += i;
}
return res;
}
}
LeetCode 134. 加油站
题目链接:134. 加油站 - 力扣(LeetCode)
思路:
注意宏观上判断一下总油够不够总花费;另外,我们初始化一个下标来遍历。对每个加油站我们都加油减油,当出现油不够跑的时候,肯定不能从这个地方作为第一个站出发,我们把初始化值+1,把当前的油重置为0。如果最后总的油够超过总花费,那么出发站之后的油肯定大于等于出发站之前所欠缺的油。
代码:
#python
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
total_gas = 0
current_gas = 0
start_station = 0
for i in range(len(gas)):
total_gas += gas[i] - cost[i]
current_gas += gas[i] - cost[i]
# 如果当前汽油量为负,则重置起始加油站,并将当前汽油量设置为0
if current_gas < 0:
start_station = i + 1
current_gas = 0
# 如果总汽油量小于0,则不可能完成环路
if total_gas < 0:
return -1
return start_station
/java
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int total_gas = 0, cur_gas = 0, start_idx = 0;
for(int i = 0; i < gas.length; i++){
total_gas += gas[i] - cost[i];
cur_gas += gas[i] - cost[i];
if(cur_gas < 0){
start_idx = i + 1;
cur_gas = 0;
}
}
if(total_gas < 0){
return -1;
}
return start_idx;
}
}
LeetCode 135. 分发糖果
题目链接:135. 分发糖果 - 力扣(LeetCode)
思路:
做编程题之前一定要读懂题目,看下条件:每个孩子至少一个糖果,如果我比身边孩子分数高肯定要给更多的糖果。那么如果一样呢?A与B都是2分,假设A有2个,B得多少糖果?应该是1个,因为B没有比A多.........好吧,注意了这个情况后开始写代码,按照卡哥思路来吧:别单独对一个孩子判断其左右,这样顾此失彼会反复作用,很麻烦,咱们从左来一次,满足条件,保持相对舒服后从右来一次,不就都满足了吗(不改变左边过来的顺序)?(卡哥牛逼!)
代码:
#python
class Solution:
def candy(self, ratings: List[int]) -> int:
candyVec = [1] * len(ratings)
# 从前向后遍历,处理右侧比左侧评分高的情况
for i in range(1, len(ratings)):
if ratings[i] > ratings[i - 1]:
candyVec[i] = candyVec[i - 1] + 1
# 从后向前遍历,处理左侧比右侧评分高的情况
for i in range(len(ratings) - 2, -1, -1):
if ratings[i] > ratings[i + 1]:
candyVec[i] = max(candyVec[i], candyVec[i + 1] + 1)
# 统计结果
result = sum(candyVec)
return result
/java
class Solution {
public int candy(int[] ratings) {
int n = ratings.length;
if(n == 1){
return 1;
}
int[] ori = new int[n];
for(int i = 0; i < n; i++){
ori[i] = 1;
}
for(int i = 1; i < n; i++){
if(ratings[i] > ratings[i - 1]){
ori[i] = ori[i - 1] + 1;
}
}
for(int j = n - 2; j > -1; j--){
if(ratings[j] > ratings[j + 1]){
ori[j] = Math.max(ori[j], ori[j + 1] + 1);
}
}
int res = 0;
for(int i : ori){
res += i;
}
return res;
}
}