1005.K次取反后最大化的数组和
贪心的思路,局部最优 :让绝对值大的负数变为正数,当前数值达到最大,整体最优:整个数组和达到最大。
局部最优可以推出全局最优。
那么如果将负数都转变为正数了,K依然大于0,此时的问题是一个有序正整数序列,如何转变K次正负,让 数组和 达到最大。
那么又是一个贪心:局部最优:只找数值最小的正整数进行反转,当前数值和可以达到最大(例如正整数数组{5, 3, 1},反转1得到-1 比 反转5得到的-5大多了),全局最优:整个数组和 达到最大。
class Solution:
def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
nums = sorted(nums)
# 优先把所有的负数变成正数
i = 0
while k :
if nums[0] < 0:
nums[0] = - nums[0]
nums = sorted(nums)
elif k % 2 == 0:
return sum(nums)
elif k % 2 != 0:
return sum(nums) - 2*nums[0]
k -= 1
return sum(nums)
134. 加油站
- 暴力法: 一次将五个站点作为初始站点,看遍历完所有的节点之后油是否够用。
转圈的情况利用while循环进行求解。 - 贪心算法1:
- 贪心算法2: 计算每一步的剩余油量值,累加每一个站点的剩余油量,如果累计的油量小于0的话,这个时候应应该将下一个结点作为开始的坐标。
最关心的是补充消耗之后是增油还是减油,所以可以利用res数组记录结余的油量,
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
res = [0] * len(gas)
for i in range(len(gas)):
res[i] = gas[i] - cost[i]
# 先做整体的剪枝
if sum(res) < 0 :
return -1
start = 0
curSum = 0
cur = 0
# 再对剩余的各种情况进行求解。
while cur < len(gas):
curSum += res[cur]
if curSum < 0:
start = cur + 1
curSum = 0
cur += 1
return start
135. 分发糖果
本题涉及到一个思想,就是 想处理好一边再处理另一边 ,不要两边想着一起兼顾,后面还会有题目用到这个思路
面临的问题是既要考虑左边的节点,又要考虑右边的节点。
- 先只确定右边的小孩比左边的小孩的得分高:从前向后遍历
- 左孩子比右孩子得分高:从后向前遍历
class Solution:
def candy(self, ratings: List[int]) -> int:
result = [1] * len(ratings)
# 从前往后找
for i in range(1,len(ratings)):
if ratings[i] > ratings[i-1]:
result[i] = result[i-1] + 1
# 从后往前找
for i in range(len(ratings)-2,-1,-1):
if ratings[i+1] < ratings[i]:
result[i] = max(result[i+1] + 1, result[i])
return sum(result)