Leetcode 1262. 可被三整除的最大和
Posted 我是小学生1994
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode 1262. 可被三整除的最大和相关的知识,希望对你有一定的参考价值。
题目:给你一个整数数组 nums,请你找出并返回能被三整除的元素最大和。
示例 1:
输入:nums = [3,6,5,1,8]
输出:18
解释:选出数字 3, 6, 1 和 8,它们的和是 18(可被 3 整除的最大和)。
这道题是第163周竞赛的一道题目,难度中等,边学别人的解题方法,边记录吧!
方案一、不妨设dp[i] 代表 选取的数字累加和 模3 = i 的数字和
假定nums[i] % 3 = 1 ,那么,和 前面选取的数字和模 3 = 2 的数相加,就可以模3为 0 ,表达起来就是 dp[0] = max(dp[0], nums[i] + dp[2])依次类推,只要不断更新 dp 数组即可,注意一点,更新的时候要保存上一个状态的值,避免后续更新的时候重复影响。
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 using namespace std; 5 6 int maxSumDivThree(vector<int>& nums) { 7 int dp[3] = { 0, 0, 0 }; 8 int i; 9 cout << "┌───────┬───────┬───────┐" << endl; 10 for (i = 0; i < nums.size(); i++) 11 { 12 //依次判断nums[i] 13 int mod = nums[i] % 3; 14 int a = dp[(3 + 0 - mod) % 3];//保留上一步的值,避免后续相加影响 15 int b = dp[(3 + 1 - mod) % 3]; 16 int c = dp[(3 + 2 - mod) % 3]; 17 18 if (a||mod == 0) dp[0] = max(dp[0], a + nums[i]); 19 if (b||mod == 1) dp[1] = max(dp[1], b + nums[i]); 20 if (c||mod == 2) dp[2] = max(dp[2], c + nums[i]); 21 cout << "│\\t" << dp[0] << "\\t│\\t" << dp[1] << "\\t│\\t" << dp[2] << "\\t│" << endl; 22 if(i<nums.size()-1) 23 cout << "├───────┼───────┼───────┤" << endl; 24 else 25 cout << "└───────┴───────┴───────┘" << endl; 26 } 27 28 return dp[0]; 29 } 30 31 vector<int> vc; 32 int main() 33 { 34 int n; 35 cin >> n; 36 vc.resize(n); 37 int i; 38 for (i = 0; i < n; i++) 39 cin>>vc[i]; 40 cout << endl; 41 cout << "能被3整除的最大和为:" <<maxSumDivThree(vc) << endl; 42 return 0; 43 }
理解:(当然这是看的别人的想法,作者https://leetcode-cn.com/u/igamegum/)
先看下运行结果吧,就用上边的实例进行解释:
1、a,b,c是干什么用的?
a,b,c应该是保留上一步的值,a、b、c的取值如下:
每次均记录了上一步的dp中的值,下一步在计算dp[0]时,dp[0]会发生变化,此时,在计算dp[1]时,用到的dp[0]不再是原始的dp[0],从而造成数据的不一致问题!
2、if(b || mod == 1)中,为什么还要判断b的值?
这里的b我理解的是,当它不为0的时候,不过mod值是不是1,我都需要去更新dp[1],因为存在mod是2,需要考虑(2+2)%3=1的情况,同样,mod为0,需要考虑(1+0)%3=1的情况;这里我们去掉试一试,看下结果:
显然,当计算第4层时,数字1%3=1,此时,dp[0]只考虑了mod=0,所以dp[0]没有进行更新,但是数字1+dp[2]也可以构成模3余0的情况,并且和为15,显然比9大!!!
方案二、国外神代码,没解释,等待理解
1 class Solution { 2 public: 3 int maxSumDivThree(vector<int>& A) { 4 vector<int> dp = {0, INT_MIN, INT_MIN}; 5 for (int a : A) { 6 vector<int> dp2 = {0, 0, 0}; 7 for (int i = 0; i < 3; ++i) 8 dp2[(i + a) % 3] = max(dp[(i + a) % 3], dp[i] + a); 9 dp = dp2; 10 } 11 return dp[0]; 12 } 13 };
理解了之后回来更新~~~
以上是关于Leetcode 1262. 可被三整除的最大和的主要内容,如果未能解决你的问题,请参考以下文章
930. 和相同的二元子数组/238. 除自身以外数组的乘积/1262. 可被三整除的最大和/NC90 设计getMin功能的栈/NC67连续子数组的最大和/NC115 栈和排序