字节笔试 - 寿司最大价格 - 动态规划 - 数组不相邻数之和最大值

寿司 - 数组不相邻数之和最大值

此题来自于朋友在字节的笔试, 同类题目可见leetcode 198题 House Robber.

给你一堆寿司 不能选相邻的盘子 然后要选出价格加起来最高的那些 print价格

举例 [9 1 4 3] 输出13

如果是[9 1 3 2 5] 输出17

从题目知道这题本质是给一组数组,求数组里不相邻元素的最大值和,也就是说,求最优解。

思路

最优解题目使用DP。

第一步是 确定状态

假设有10碟寿司,价格如下

寿司序列[0][1][2][3][4][5][8][9]
价格914356810

不管是哪种组合,都存在算进组合里的最后一碟。

第二步,转移方程

O P T ( 9 ) OPT(9) OPT(9) --> 定义为当选择寿司[9]作为最后一步的最优解。

会出现两种情况:

如果选择寿司[9]作为最后一碟,那么因为题目元素不相邻的性质, 下一步计算不能选择寿司[8]。需要选择寿司[7],那么 O P T ( 9 ) = O P T ( 7 ) + a r r [ 9 ] OPT(9) = OPT(7)+arr[9] OPT(9)=OPT(7)+arr[9] . 简单来说就是当最后一步为寿司[7]的时候 ( O P T ( 7 ) ) OPT(7)) OPT(7)),加上寿司[9]的价格就是 O P T ( 9 ) OPT(9) OPT(9).

如果不选择寿司[9]作为最后一碟,那么我们只能选择[8]作为最后一碟,因为题目性质,最后一步必须为[8] 和[9]的其中之一。这种情况就是 O P T ( 8 ) OPT(8) OPT(8).

把整个算法步骤转为树状图:
在这里插入图片描述

总结就是,每一个最优解 O P T ( i ) OPT(i) OPT(i) 都有选和不选两种选择,如下:

在这里插入图片描述

也就是 $OPT(i) = $ max { O P T ( i − 2 ) + a r r [ i ] , O P T ( i − 1 ) OPT(i-2)+arr[i], OPT(i-1) OPT(i2)+arr[i],OPT(i1)}, 这个就是我们的**状态转移方程 **。

到这里已经是解开一半了,能通过递归求解得出,但是效率会很慢,因为有多个重复计算。

第三步,初始条件和边界条件

很明显,

初始条件 OPT(0) = arr[0], OPT(1) = MAX{ a r r [ 0 ] , a r r [ 1 ] arr[0], arr[1] arr[0],arr[1]}

第四步,计算顺序

这一步是为了优化效率,为了记录计算结果,不重复计算,从左到右开始算起。也即是 先从OPT(i=0)开始,然后往后计算。

代码

class Solution:
    def sushi(self, nums: List[int]) -> int:
        size = len(nums)
        if (size == 0):
            res = 0
        elif size == 1:
            res = int(nums[0])
        # 边界条件
        else:
            # size >= 3 
            # 计算顺序从左到右
            sum_a = nums[0]  # 初始条件
            sum_b = max(nums[0], nums[1])
            for i in range(2, size):
                temp = max(sum_a + nums[i], sum_b)
                sum_a = sum_b
                sum_b = temp
            res = int(max(sum_a, sum_b))
        return res
    
            
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值