22年48周

最近两周刷了刷贪心和动态规划的题目,可以说这两类题目还是比较难想的。

目录

1.买卖股票的最佳时机II

2.跳跃游戏

3.跳跃游戏II

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

5.加油站

6.柠檬水找零


1.买卖股票的最佳时机II

题目:买卖股票的最佳时机II

思路:局部最优:收集每天的正利润,全局最优:求得最大利润

原因就是有这个递推公式:

假如第0天买入,第3天卖出,那么利润为:prices[3] - prices[0]。

相当于(prices[3] - prices[2]) + (prices[2] - prices[1]) + (prices[1] - prices[0])。

此时就是把利润分解为每天为单位的维度,而不是从0天到第3天整体去考虑!

所以只要第二天能获利,就当天买入,第二天卖出

func maxProfit(prices []int) int {
    result := 0 

    for i:=1;i<len(prices);i++ {
        if prices[i] - prices[i-1] > 0 {
            result += prices[i] - prices[i-1]
        }
    }
    return result
}

2.跳跃游戏

题目:跳跃游戏

思路:每跳一次都去选择,如果跳到这一个节点i,nums[i] + i 和假如没跳到这个节点来讲,哪个覆盖率更大一点,就选择是否跳到该节点。

贪心算法局部最优解:每次取最大跳跃步数(取最大覆盖范围),整体最优解:最后得到整体最大覆盖范围,看是否能到终点

55.跳跃游戏

 

func canJump(nums []int) bool {
    if len(nums) <= 1 {
        return true
    }
    n := len(nums)
    cover := 0
    //[4,2,0,0,1,1,4,4,4,0,4,0]
    for i:=0;i<=cover;i++ {
        //i代表当前的位置
        //nums[i]表示,加上当前的这个能挑到最远的位置
        cover = max(i+nums[i],cover)
        if cover >= n-1 {
            return true
        }
    }
    return false
}

func max(a, b int ) int {
    if a > b {
        return a
    }
    return b
}

3.跳跃游戏II

题目:跳跃游戏II

思路:

func jump(nums []int) int {
    n := len(nums)
    if n == 1 {
        return 0
    }
    cur, next := 0, 0
    step := 0
    for i := 0; i < n-1; i++ {
        next = max(nums[i]+i, next)
        if i == cur {
            cur = next
            step++
        }
    }
    return step
}

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

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

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

思路:这道题其实还是比较好想的,先排序,之后把小于零的全都取反,

之后再排序,看取反次数还剩多少,偶数个的话,就是数组和

奇数个的话,就是首元素取反之后的数组和。

func largestSumAfterKNegations(nums []int, k int) int {

    sort.Ints(nums)
    index := 0
    i:=0
    //有小于0的直接逆反
    for ;i<k;i++ {
        if index < len(nums) && nums[index] < 0 {
            nums[index] = -nums[index]
            index++
        }else{
            break
        }
    }
    sort.Ints(nums)
    //全大于0则逆反最小的
    for ;i<k;i++ {
        nums[0] = -nums[0]
    }
    all := 0 
    for _,v := range nums {
        all += v
    }
    return all
}

5.加油站

题目:加油站

思路:

首先如果总油量减去总消耗大于等于零那么一定可以跑完一圈,说明 各个站点的加油站 剩油量rest[i]相加一定是大于等于零的。

每个加油站的剩余量rest[i]为gas[i] - cost[i]。

i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i]区间都不能作为起始位置,起始位置从i+1算起,再从0计算curSum。

func canCompleteCircuit(gas []int, cost []int) int {
    total := 0
    partTotal := 0
    start := 0

    for i:=0;i<len(gas);i++ {
        total += gas[i] - cost[i]
        partTotal += gas[i] - cost[i]
        if partTotal < 0 {
            start = i+1
            partTotal = 0
        }
    }
    if total < 0 {
        return -1
    }
    return start
}

6.柠檬水找零

题目:柠檬水找零

思路:这道题用简单的模拟就能完成。优先使用5元的来找零

func lemonadeChange(bills []int) bool {
    if bills[0] != 5 {
        return false
    }

    billsMap := make(map[int]int)

    for _,v := range bills {
        if v == 5 {
            billsMap[v]++
        }
        if v == 10 {
            billsMap[5]--
            if billsMap[5] < 0 {
                return false
            }
            billsMap[10]++
        }
        if v == 20 {
            if billsMap[10] > 0 {
                billsMap[10]--
                billsMap[5]--
                if billsMap[5] < 0 {
                    return false
                }
            }else {
                billsMap[5] -= 3
                if billsMap[5] < 0 {
                    return false
                }
            }
        }
    }
    return true
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值