主要内容
- 贪心
- 链表
贪心题目
1005.K次取反后最大化的数组和
思路分析
# (1) 如果最小值大于0,且k为偶数,不动;
# (2) 如果最小值大于0,且k为奇数,最小值变负;
# (3) 如果最小值小于0,先从小到大把负的变为正的:
# (4) 若不能全变为正的,此时就为最大
# (5) 若均为正的,此时回到(1)(2)
贪心的思想:局部最优,再达到全局最优
代码
# leetcode submit region begin(Prohibit modification and deletion)
class Solution:
def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
# 排序
nums = sorted(nums)
# (1) 如果最小值大于0,且k为偶数,不动;
# (2) 如果最小值大于0,且k为奇数,最小值变负;
# (3) 如果最小值小于0,先从小到大把负的变为正的:
# (4) 若不能全变为正的,此时就为最大
# (5) 若均为正的,此时回到(1)(2)
if nums[0] >= 0:
if k % 2:
return -nums[0] + sum(nums[1:])
else:
return sum(nums)
else:
for i in range(len(nums)):
if nums[i] < 0 and k > 0:
nums[i] = -nums[i]
k -= 1
nums = sorted(nums)
if nums[0] < 0:
return sum(nums)
else:
if k % 2:
return -nums[0] + sum(nums[1:])
else:
return sum(nums)
# leetcode submit region end(Prohibit modification and deletion)
class Solution:
def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
# 按绝对值从大到小排序排序
# 遇到负的给变正
# 如果还有k,最小的变负
nums = sorted(nums, key=abs, reverse=True)
for i in range(len(nums)):
if nums[i] < 0 and k > 0:
nums[i] *= -1
k -= 1
if k % 2:
nums[len(nums) - 1] *= -1
return sum(nums)
134. 加油站
思路分析
暴力解法超时了,采用下面方法,遍历一次
代码
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
# [i,j] 的cursum 小于0,则起点需从j+1开始遍历
start = 0
cursum = 0
totalsum = 0
for i in range(len(gas)):
cursum += gas[i] - cost[i]
totalsum += gas[i] - cost[i]
if cursum < 0:
start = i + 1
cursum = 0
if totalsum < 0:
return -1
return start
135. 分发糖果
思路分析
巧妙的贪心
一次是从左到右遍历,只比较右边孩子评分比左边大的情况。
一次是从右到左遍历,只比较左边孩子评分比右边大的情况。
代码
class Solution:
# (1) 先从左向右找,遇到比左边大的就加1;
# (2) 再从右向左找,遇到比右边大的就加1,取最大
def candy(self, ratings: List[int]) -> int:
n = len(ratings)
res = [1] * n
for i in range(1, n):
if ratings[i] - ratings[i-1] > 0:
res[i] = res[i-1] + 1
for i in range(n-2,-1,-1):
if ratings[i] - ratings[i+1] > 0:
res[i] = max(res[i], res[i+1]+1)
return sum(res)