[代码随想录]Day29-贪心算法part03
1.[代码随想录]Day01-数组part012.[代码随想录]Day02-数组part023.[代码随想录]Day06-哈希表 part024.[代码随想录]Day05-哈希表 part015.[代码随想录]Day04-链表part026.[代码随想录]Day03-链表part017.[代码随想录]Day14-二叉树part038.[代码随想录]Day13-二叉树part029.[代码随想录]Day12-二叉树part0110.[代码随想录]Day11-栈与队列part0311.[代码随想录]Day10-栈与队列part0212.[代码随想录]Day09-栈与队列part0113.[代码随想录]Day08-字符串 part0214.[代码随想录]Day07-字符串 part0115.[代码随想录]Day30-贪心算法part04
16.[代码随想录]Day29-贪心算法part03
17.[代码随想录]Day28-贪心算法part0218.[代码随想录]Day27-贪心算法part0119.[代码随想录]Day26-回溯算法part0620.[代码随想录]Day25-回溯算法part0521.[代码随想录]Day24-回溯算法part0422.[代码随想录]Day23-回溯算法part0323.[代码随想录]Day22-回溯算法part0224.[代码随想录]Day21-回溯算法part0125.[代码随想录]Day20-二叉树part0926.[代码随想录]Day19-二叉树part0827.[代码随想录]Day18-二叉树part0728.[代码随想录]Day17-二叉树part0629.[代码随想录]Day16-二叉树part0530.[代码随想录]Day15-二叉树part0431.[代码随想录]Day52-单调栈part0332.[代码随想录]Day51-单调栈part0233.[代码随想录]Day50-单调栈part0134.[代码随想录]Day49-动态规划part1735.[代码随想录]Day48-动态规划part1636.[代码随想录]Day47-动态规划part1537.[代码随想录]Day46-动态规划part1438.[代码随想录]Day45-动态规划part1339.[代码随想录]Day44-动态规划part1240.[代码随想录]Day43-动态规划part1141.[代码随想录]Day42-动态规划part1042.[代码随想录]Day41-动态规划part0943.[代码随想录]Day40-动态规划part0844.[代码随想录]Day39-动态规划part0745.[代码随想录]Day38-动态规划part0646.[代码随想录]Day37-动态规划part0547.[代码随想录]Day36-动态规划part0448.[代码随想录]Day35-动态规划part0349.[代码随想录]Day34-动态规划part0250.[代码随想录]Day33-动态规划part0151.[代码随想录]Day32-贪心算法part0652.[代码随想录]Day31-贪心算法part05题目:1005.K次取反后最大化的数组和
思路:
思路是:
- 先把负数从小到大变成正数(即绝对值由大到小)
- 如果还需要变化(k>0),就变化最小的数
在第一步变化的同时顺便记录一个数组和,那么结束之后会有三种情况:
- k == 0;也就是说负数的个数大于等于k,直接返回结果
- k % 2 == 0; 此时全是正整数,如果k是偶数的话,可以相当于没有变化,直接返回结果
- k % 2 != 0; 此时全是正整数,如果k是奇数的话,需要把最小的数变成负数,因为之前res里已经添加了最小,因此需要
- 2 * nums[0]
。
代码1:
func largestSumAfterKNegations(nums []int, k int) int {
res := 0
lens := len(nums)
sort.Ints(nums) // 排序
for i := 0; i < lens; i++ { // 一边把负数变正一边求和
if nums[i] >= 0 { // 求和1
res += nums[i]
continue
}
if k > 0 { // 如果k大于0就可以变
nums[i] = -nums[i]
k--
}
res += nums[i] // 求和2
}
sort.Ints(nums) // 变完之后再排序一次
if k % 2 == 1 { // 如果k剩下奇数个,把最小的元素去掉即可(因为之前加了,所以要减去2 * nums[0]
res -= 2 * nums[0]
}
return res
}
代码2:
func largestSumAfterKNegations(nums []int, k int) int {
res := 0
lens := len(nums)
sort.Slice(nums, func(i, j int) bool { // 用这个直接求绝对值的排序(由大到小)
return math.Abs(float64(nums[i])) > math.Abs(float64(nums[j]))
})
for i := 0; i < lens; i++ {
if nums[i] >= 0 {
res += nums[i]
continue
}
if k > 0 { // 这样也会先添加大的负数
nums[i] = -nums[i]
k--
}
res += nums[i]
}
if k % 2 == 1 {
res -= 2 * nums[lens-1] // 最小的元素是nums[lens-1]
}
return res
}
参考:
题目:134. 加油站
思路:
其实这个思路和最大子序列和差不多:如果正向是负向效果(油会更少),那么在这里开始肯定不行所以没必要遍历这种index,如果是正向效果,那我的tmp之前有数的话岂不是更好?所以直接for一边就可以。
代码:
func canCompleteCircuit(gas []int, cost []int) int {
gas = append(gas, gas...)
cost = append(cost, cost...)
lens := len(gas)
tmp := 0
index := 0 // 记录起始位置
for i := 0; i < lens; i++ {
tmp += gas[i] - cost[i] // 记录当前剩下的油
if tmp < 0 { // 小于0就跑不了
tmp = 0
index = i + 1 // 试试下一个点
continue
}
if i - index == lens / 2 - 1 { // 如果跑完了全程就返回index
return index
}
}
return -1
}
参考:
题目:135. 分发糖果
思路:
本题采用了两次贪心的策略:
一次是从左到右遍历,只比较右边孩子评分比左边大的情况。
一次是从右到左遍历,只比较左边孩子评分比右边大的情况。
这样从局部最优推出了全局最优,即:相邻的孩子中,评分高的孩子获得更多的糖果。
代码:
func candy(ratings []int) int {
/**先确定一边,再确定另外一边
1.先从左到右,当右边的大于左边的就加1
2.再从右到左,当左边的大于右边的就再加1
**/
need := make([]int, len(ratings))
sum := 0
// 初始化(每个人至少一个糖果)
for i := 0; i < len(ratings); i++ {
need[i] = 1
}
// 1.先从左到右,当右边的大于左边的就加1
for i := 0; i < len(ratings) - 1; i++ {
if ratings[i] < ratings[i+1] {
need[i+1] = need[i] + 1
}
}
// 2.再从右到左,当左边的大于右边的就右边加1,但要花费糖果最少,所以需要做下判断
for i := len(ratings)-1; i > 0; i-- {
if ratings[i-1] > ratings[i] {
need[i-1] = findMax(need[i-1], need[i]+1)
}
}
//计算总共糖果
for i := 0; i < len(ratings); i++ {
sum += need[i]
}
return sum
}
func findMax(num1 int, num2 int) int {
if num1 > num2 {
return num1
}
return num2
}
参考:
合集:
代码随想录
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!