首页 > 编程语言 >[代码随想录]Day29-贪心算法part03

[代码随想录]Day29-贪心算法part03

时间:2023-08-28 16:35:40浏览次数:42  
标签:ratings Day29 nums int res part03 随想录 lens return

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

思路:

思路是:

  1. 先把负数从小到大变成正数(即绝对值由大到小)
  2. 如果还需要变化(k>0),就变化最小的数

在第一步变化的同时顺便记录一个数组和,那么结束之后会有三种情况:

  1. k == 0;也就是说负数的个数大于等于k,直接返回结果
  2. k % 2 == 0; 此时全是正整数,如果k是偶数的话,可以相当于没有变化,直接返回结果
  3. 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
}

参考:

代码随想录

标签:ratings,Day29,nums,int,res,part03,随想录,lens,return
From: https://www.cnblogs.com/wtcsky/p/17661526.html

相关文章

  • 代码随想录第4天|链表复习
    做这种算法题真的要放平心态,你想不到思路的时候不要觉得自己太笨,其实想不到很正常,今天环形链表和相交链表这两道题,真的一点思路都没有,环形链表是最难理解的,在课堂上学的链表上的那点东西拿来做这种题确实还是差很多,我真的非常感谢这个做题的训练营,没有它我自己真的做不下去,现在跟......
  • 代码随想录算法训练营第二十四天| 理论基础 77. 组合
     理论基础    卡哥建议:其实在讲解二叉树的时候,就给大家介绍过回溯,这次正式开启回溯算法,大家可以先看视频,对回溯算法有一个整体的了解。   题目链接/文章讲解:https://programmercarl.com/%E5%9B%9E%E6%BA%AF%E7%AE%97%E6%B3%95%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%8......
  • 代码随想录算法训练营第二十三天| 669. 修剪二叉搜索树 108.将有序数组转换为二叉搜
     669. 修剪二叉搜索树    卡哥建议:这道题目比较难,比 添加增加和删除节点难的多,建议先看视频理解。   题目链接/文章讲解:https://programmercarl.com/0669.%E4%BF%AE%E5%89%AA%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91.html   视频讲解:https://www.......
  • 代码随想录算法训练营第二十二天| 235. 二叉搜索树的最近公共祖先 701.二叉搜索树
      235. 二叉搜索树的最近公共祖先    卡哥建议:相对于 二叉树的最近公共祖先 本题就简单一些了,因为 可以利用二叉搜索树的特性。   题目链接/文章讲解:https://programmercarl.com/0235.%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E7%9A%84%E6%9C%80%E8%B......
  • 代码随想录第三天|203.移除列表元素;707.设计链表;206.反转链表
    今天最大的收获不是学会了几道题,而是突然改变了自己之前的想法,总想刷一遍就能把题弄回,这样在遇到难题时会拖延很长的时间,备受挫折,做一两道题就再也不想做了,刷题也就终止了应该做好刷三遍题的准备,第一遍,大量看题,看解题思路,在看题的过程中积累知识和解题技巧,不要迷恋在某一道题上,看......
  • [代码随想录]Day27-贪心算法part01
    题目:455.分发饼干思路:贪心,思路是尽量先给胃口值小的分,饼干也是从小的开始分:如果饼干满足了胃口值,结果+1换下一个人,下一个饼干如果饼干满足不了胃口值,换下一个饼干(满足不了胃口值小的一定满足不了大的)代码:funcfindContentChildren(g[]int,s[]int)int{res:=......
  • 代码随想录第二天|977.有序数组的平方;209.长度最小的子数组;59.螺旋矩阵II,总结
    今天的这三道题每道题对我来说都不简单,有序数组的平方和长度最小的子数组这两道题还能用暴力求解,螺旋矩阵看着简单却没有思路,磨了半小时还是决定直接看讲解有序数组平方和用的双指针的思想,代码如下:1classSolution{2public:3vector<int>sortedSquares(vector<int......
  • [代码随想录]Day26-回溯算法part06
    题目:332.重新安排行程思路:其实这里已经是图的部分了,回溯应该也可以。Hierholzer算法解决欧拉问题代码:funcfindItinerary(tickets[][]string)[]string{var(m=map[string][]string{}res[]string)for_,ticket:=rangeticket......
  • 代码随想录第一天|704.二分查找、27.移除元素
    二分查找对数组的要求有两点:有序无重复元素,若有重复元素则返回的元素下标不唯一边界条件是while(left<=right)代码其实是很好理解的点击查看代码classSolution{public:intsearch(vector<int>&nums,inttarget){intlength=nums.size();......
  • [代码随想录]Day25-回溯算法part05
    题目:491.递增子序列思路:核心问题——同层去重,这一题不能够重新排序因此不可以用i>index&&nums[i]==nums[i-1]来去重,而是每一层开一个map来判断该数是否出现过代码:var(res[][]intpath[]int)funcfindSubsequences(nums[]int)[][]int{res=make(......