【LeetCode1262】 可被三整除的最大和(动态规划)

举报
野猪佩奇996 发表于 2022/01/30 23:26:19 2022/01/30
【摘要】 一、题目 提示: 1 <= nums.length <= 4 * 10^4 1 <= nums[i] <= 10^4 二、思路 要从给出的数组中,找到一小坨数满足和能被3整...

一、题目

在这里插入图片描述
提示:
1 <= nums.length <= 4 * 10^4
1 <= nums[i] <= 10^4

二、思路

要从给出的数组中,找到一小坨数满足和能被3整除。dp[i][*]表示在num[i]中,被3整除后的余数为*的最大数(和)。

2.1 确定状态

对于每种状态,有2种选择:选择当前元素;不选择当前元素:

	dp[i][*] = max{dp[i-1][*],dp[i-1][*] + nums[i]}  (* 取值为 0,1,2)

  
 
  • 1

2.2 转移方程

(1)零状态:
dp[k][0]:能够被3整除余0的最大数(和)。
d p [ i ] [ 0 ] = max ⁡ ( d p [ i − 1 ] [ 0 ] , { d p [ i − 1 ] [ 0 ] + n u m s [ i ]  nums  [ i ] % 3 = = 0 d p [ i − 1 ] [ 1 ] + n u m s [ i ]  nums  [ i ] % 3 = = 2 d p [ i − 1 ] [ 2 ] + n u m s [ i ]  nums  [ i ] % 3 = = 1 ) d p[i][0]=\max \left(d p[i-1][0],\left\{

dp[i1][0]+nums[i]dp[i1][1]+nums[i]dp[i1][2]+nums[i] nums [i]%3==0 nums [i]%3==2 nums [i]%3==1 d p [ i 1 ] [ 0 ] + n u m s [ i ]  nums  [ i ] % 3 == 0 d p [ i 1 ] [ 1 ] + n u m s [ i ]  nums  [ i ] % 3 == 2 d p [ i 1 ] [ 2 ] + n u m s [ i ]  nums  [ i ] % 3 == 1
dp[i][0]=maxdp[i1][0],dp[i1][0]+nums[i]dp[i1][1]+nums[i]dp[i1][2]+nums[i] nums [i]%3==0 nums [i]%3==2 nums [i]%3==1

dp[k][1] d p [ i ] [ 1 ] = max ⁡ ( d p [ i − 1 ] [ 1 ] , { d p [ i − 1 ] [ 0 ] + n u m s [ i ] , n u m s % 3 = = 1 d p [ i − 1 ] [ 1 ] + n u m s [ i ] , n u m s [ i ] % 3 = = 0 d p [ i − 1 ] [ 2 ] + n u m s [ i ] , n u m s [ i ] % 3 = = 2 ) d p[i][1]=\max \left(d p[i-1][1],\left\{
dp[i1][0]+nums[i]dp[i1][1]+nums[i]dp[i1][2]+nums[i]nums%3==1nums[i]%3==0nums[i]%3==2 d p [ i 1 ] [ 0 ] + n u m s [ i ] n u m s % 3 == 1 d p [ i 1 ] [ 1 ] + n u m s [ i ] n u m s [ i ] % 3 == 0 d p [ i 1 ] [ 2 ] + n u m s [ i ] n u m s [ i ] % 3 == 2
\right)\right.
dp[i][1]=maxdp[i1][1],dp[i1][0]+nums[i]dp[i1][1]+nums[i]dp[i1][2]+nums[i]nums%3==1nums[i]%3==0nums[i]%3==2


dp[k][2] d p [ i ] [ 2 ] = max ⁡ ( d p [ i − 1 ] [ 2 ] , { d p [ i − 1 ] [ 0 ] + n u m s [ i ] nums ⁡ [ i ] % 3 = = 2 d p [ i − 1 ] [ 1 ] + n u m s [ i ]  nums  [ i ] % 3 = = 1 d p [ i − 1 ] [ 2 ] + n u m s [ i ]  nums  [ i ] % 3 = 0 ) d p[i][2]=\max \left(d p[i-1][2],\left\{
dp[i1][0]+nums[i]dp[i1][1]+nums[i]dp[i1][2]+nums[i]nums[i]%3==2 nums [i]%3==1 nums [i]%3=0 d p [ i 1 ] [ 0 ] + n u m s [ i ] nums [ i ] % 3 == 2 d p [ i 1 ] [ 1 ] + n u m s [ i ]  nums  [ i ] % 3 == 1 d p [ i 1 ] [ 2 ] + n u m s [ i ]  nums  [ i ] % 3 = 0
\right)\right.
dp[i][2]=maxdp[i1][2],dp[i1][0]+nums[i]dp[i1][1]+nums[i]dp[i1][2]+nums[i]nums[i]%3==2 nums [i]%3==1 nums [i]%3=0

2.3 初始条件+边界

因为当前的状态和前一个状态有关,(我们先将遍历的i从1开始遍历),则其中第0个状态的dp[0][0]表示在nums[0]中,能够被3整除余0的最大数,此时还没遍历到数,dp[0][0] = 0,相当于给数组头添加了0。

还有dp[0][1] = INT_MIN; dp[0][2] = INT_MIN;, 如果设置成0是不符合定义的,dp[0][1]表示的是模三余一,dp[0][2]表示的是模三余二。

这里dp[i][1]dp[i][2]的初始值可以理解为无穷小,因为dp[i][1]dp[i][2]的第一个有意义的初始值可以理解为dp[i-1][0]加上数组当前值nums[i]构成的,又因为每次更新三个状态是通过比较最大值获得的,所以无穷小就被干掉了。

举个例子,假设有一个数组中第一个%3余1的数是4,那么在4出现之前,dp[i][1]就一直是无穷小,不会影响dp[i][0]的更新。只有4出现了,才会用dp[i-1][0] + 4去更新dp[i][1],之后dp[i][1]才会参与dp[i][0]的更新。

2.4 计算顺序

根据递推公式,如dp[i][0]是由dp[i - 1][0]决定的,所以i从小到大顺序遍历。

三、代码

class Solution {
public:
    int maxSumDivThree(vector<int>& nums) {
        int n = nums.size();
        vector<vector<int>> dp(n + 1, vector<int>(3, 0));

        dp[0][0] = 0;
        dp[0][1] = INT_MIN;
        dp[0][2] = INT_MIN;

        for(int i = 1;  i <= n; i++){
            if(nums[i - 1] % 3 == 0){
                dp[i][0] = max(dp[i - 1][0], dp[i - 1][0] + nums[i - 1]);
                dp[i][1] = max(dp[i - 1][1], dp[i - 1][1] + nums[i - 1]);
                dp[i][2] = max(dp[i - 1][2], dp[i - 1][2] + nums[i - 1]);
            }else if(nums[i - 1] % 3 == 1){
                dp[i][0] = max(dp[i - 1][0], dp[i - 1][2] + nums[i - 1]);
                dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + nums[i - 1]);
                dp[i][2] = max(dp[i - 1][2], dp[i - 1][1] + nums[i - 1]);
            }else if(nums[i - 1] % 3 == 2){
                dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + nums[i - 1]);
                dp[i][1] = max(dp[i - 1][1], dp[i - 1][2] + nums[i - 1]);
                dp[i][2] = max(dp[i - 1][2], dp[i - 1][0] + nums[i - 1]);
            }
        }
        return dp[n][0];
    }
};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

在这里插入图片描述

文章来源: andyguo.blog.csdn.net,作者:山顶夕景,版权归原作者所有,如需转载,请联系作者。

原文链接:andyguo.blog.csdn.net/article/details/122740419

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。