leetcode第1262题可被三整除的最大和

这道LeetCode题目要求找出整数数组中能被三整除的最大和。通过动态规划,根据当前数字模3的余数来更新三种状态:被三整除、除三余1、除三余2,从而求得最大和。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

leetcode第1262题 可被三整除的最大和

题目

可被三整除的最大和

给你一个整数数组 nums,请你找出并返回能被三整除的元素最大和。

思路

每个数只有选和不选两种状态,那么根据什么转移呢,因根据当前数模3之后3的余数来进行转移。

  • dp[i][0]=到i为止被三整除的最大和
  • dp[i][1]=到i为止除三余1的最大和
  • dp[i][2]=到i为止除三余2的最大和
  1. 当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]);
  1. 当nums[i-1]%3==1时,那加入nums[i]之后,本来余0的就会余1,本来余1的余2,本来余2的余0
 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]);
}
  1. 同理,如果当前数字除以3余2,那加入nums[i]之后,本来余0的就会余2,本来余1的就会余0,本来余2的就会余1
 //如果当前数字除以3余2,那加入nums[i]之后,本来余0的就会余2,本来余1的就会余0,本来余2的就会余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]);
}

最后返回dp[n][0]

代码

class Solution {
public:
    //dp[i][0]=到i为止被三整除的最大和
    //dp[i][1]=到i为止除三余1的最大和
    //dp[i][2]=到i为止除三余2的最大和
    int maxSumDivThree(vector<int>& nums) {
        int n=nums.size();
        vector<vector<int>>dp(n+1,vector<int>(3));
         dp[0][0] = 0, dp[0][1] = -0x3f3f3f3f, dp[0][2] = -0x3f3f3f3f;
        for(int i=1;i<=n;i++)
        {
            //如果当前数字可以被3整除,那加入nums[i]之后就不会影响除3的结果
            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]);
            }
            //如果当前数字除以3余1,那加入nums[i]之后,本来余0的就会余1,本来余1的余2,本来余2的余0
            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]);
            }
            //如果当前数字除以3余2,那加入nums[i]之后,本来余0的就会余2,本来余1的就会余0,本来余2的就会余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];
    }
};

简化版本(来自leetcode题解)

class Solution {
public:
    int maxSumDivThree(vector<int>& nums) {
        int n = nums.size(), sum = 0;
        vector<vector<int>> f(n + 1, vector<int>(3));
        f[0][0] = 0, f[0][1] = -0x3f3f3f3f, f[0][2] = -0x3f3f3f3f;
        for(int i=1;i<=n;i++) {
            int x = nums[i - 1] % 3;
            f[i][0] = max(f[i-1][0], f[i-1][(3 - x)%3] + nums[i-1]);
            f[i][1] = max(f[i-1][1], f[i-1][(3-x+1)%3] + nums[i-1]);
            f[i][2] = max(f[i-1][2], f[i-1][(3-x+2)%3] + nums[i-1]);
        }
        return f[n][0];
    }
};

作者:mt19937
链接:https://leetcode-cn.com/problems/greatest-sum-divisible-by-three/solution/xian-xing-dp-by-mt19937-etfv/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值