代码随想录 day34 第八章 贪心算法 part03

本文介绍了LeetCode中的三道题目:1005.K次取反后最大化数组和、134.加油站问题(单向行驶)和135.分发糖果,分别运用了贪心算法和优先处理策略来求解。
摘要由CSDN通过智能技术生成

●  1005.K次取反后最大化的数组和

●  134. 加油站

●  135. 分发糖果

1005.K次取反后最大化的数组和

关联 leetcode 1005.K次取反后最大化的数组和

  • 思路

    • 优先对负数取反
      • 优先对绝对值最大的负数取反
    • 贪两次
      1. 先将所有负数取反 ===》全正整数
      2. 将最小的数进行剩下的取反操作
  • 题解

    func largestSumAfterKNegations(nums []int, k int) int {
    	res := 0
    	// 对数组按绝对值排序: 倒序排列,保证优先处理到的是最大的负数
    	sort.Slice(nums, func(i, j int) bool {
    		fi := float64(nums[i])
    		fj := float64(nums[j])
    		return math.Abs(fi) > math.Abs(fj)
    	})
    
    	for i := 0; i < len(nums); i++ {
    		if nums[i] < 0 && k > 0 { //翻转负数
    			nums[i] = -nums[i]
    			k--
    		}
    	}
    
    	// 翻转当前数组最小数剩下的k次
    	if k%2 == 1 {//
    		nums[len(nums)-1] *= -1
    	}
    
    	for _, num := range nums {
    		res += num
    	}
    	return res
    }
    

134. 加油站

关联 leetcode 134. 加油站

  • 思路

    • 单向行驶,运动方向固定
    • 先收获当前加油站的汽油,再开向下一个加油站,消耗汽油
    • 如果有解只有唯一解
      • 找到合法解就返回
    • 有效出发点:
      • 获得 汽油数>消耗数
        • 贪最多的
    • 当前累计油耗 < 0:
      • 从该位置的后一个位置出发
  • 题解

    func canCompleteCircuit(gas []int, cost []int) int {
    	res := 0 //默认从第0号索引出发 即 第一个元素
    	curSum, totalSum := 0, 0
    
    	for i := 0; i < len(gas); i++ {
    		curSum += gas[i] - cost[i]
    		totalSum += gas[i] - cost[i] //总数直接累计
    
    		if curSum < 0 { //当前累计剩余油量小于零, 从改该位置后一个位置开始出发
    			res = i + 1 //从下一个位置开始
    			curSum = 0  //curSum重新从0开始累计
    		}
    	}
    	if totalSum < 0 { //总剩余油量totalSum小于0,说明无法环绕一圈
    		return -1
    	}
    
    	return res
    }
    

135. 分发糖果

关联 leetcode 135. 分发糖果

  • 思路

    • 先确定比较每一个孩子的左边(/右边), 再去比较剩余的那边
      • 如果两边一起比较一定会顾此失彼
    • 贪心
      • 先贪右边, 右边评分更高
        • 从前往后遍历
        • 局部最优
          • 右边评分 > 左边
            • 右边糖果+1
        • 全局最优
          • 相邻孩子:
            • 评分高的右孩子比左孩子有更多糖果
      • 再贪左边
        • 从后往前遍历
        • 局部最优
          • 取 (当前孩子的糖果数量) 和 (右孩子+1) 相比最大的值
        • 全局最优
          • 当前中间评分最高的孩子比他 左边 和 右边 的糖果都多
      • 最终
        • 相邻孩子,评分更高的糖果更多
  • 题解

    func candy(ratings []int) int {
    	res := 0
    	//初始化分糖数组, 每个值都是1, 保证最小一颗
    	candyArr := make([]int, len(ratings))
    	for i := 0; i < len(candyArr); i++ {
    		candyArr[i] = 1
    	}
    
    	//向右贪
    	for i := 1; i < len(ratings); i++ {
    		if ratings[i] > ratings[i-1] {
    			candyArr[i] = candyArr[i-1] + 1
    		}
    	}
    	//向左贪
    	for i := len(ratings) - 1; i > 0; i-- {
    		if ratings[i-1] > ratings[i] {
    
    			candyArr[i-1] = max(candyArr[i-1], candyArr[i]+1)
    		}
    	}
    	for _, c := range candyArr {
    		res += c
    	}
    	return res
    }
    func max(a, b int) int {
    	if a > b {
    		return a
    	}
    	return b
    }
    

  • 23
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值