Description# Given an integer array nums
, return the maximum possible sum of elements of the array such that it is divisible by three .
Example 1:
Input: nums = [3,6,5,1,8]
Output: 18
Explanation: Pick numbers 3, 6, 1 and 8 their sum is 18 (maximum sum divisible by 3).Example 2:
Input: nums = [4]
Output: 0
Explanation: Since 4 is not divisible by 3, do not pick any number.
Example 3:
Input: nums = [1,2,3,4,4]
Output: 12
Explanation: Pick numbers 1, 3, 4 and 4 their sum is 12 (maximum sum divisible by 3).
Constraints:
1 <= nums.length <= 4 * 104
1 <= nums[i] <= 104
Solutions# Solution 1: Dynamic Programming# We define f [ i ] [ j ] f[i][j] f [ i ] [ j ] as the maximum sum of several numbers selected from the first i i i numbers, such that the sum modulo 3 3 3 equals j j j . Initially, f [ 0 ] [ 0 ] = 0 f[0][0]=0 f [ 0 ] [ 0 ] = 0 , and the rest are − ∞ -\infty − ∞ .
For f [ i ] [ j ] f[i][j] f [ i ] [ j ] , we can consider the state of the i i i th number x x x :
If we do not select x x x , then f [ i ] [ j ] = f [ i − 1 ] [ j ] f[i][j]=f[i-1][j] f [ i ] [ j ] = f [ i − 1 ] [ j ] ; If we select x x x , then f [ i ] [ j ] = f [ i − 1 ] [ ( j − x m o d 3 + 3 ) m o d 3 ] + x f[i][j]=f[i-1][(j-x \bmod 3 + 3)\bmod 3]+x f [ i ] [ j ] = f [ i − 1 ] [( j − x mod 3 + 3 ) mod 3 ] + x . Therefore, we can get the state transition equation:
f [ i ] [ j ] = max f [ i − 1 ] [ j ] , f [ i − 1 ] [ ( j − x m o d 3 + 3 ) m o d 3 ] + x
f[i][j]=\max{f[i-1][j],f[i-1][(j-x \bmod 3 + 3)\bmod 3]+x}
f [ i ] [ j ] = max f [ i − 1 ] [ j ] , f [ i − 1 ] [( j − x mod 3 + 3 ) mod 3 ] + x
The final answer is f [ n ] [ 0 ] f[n][0] f [ n ] [ 0 ] .
The time complexity is O ( n ) O(n) O ( n ) , and the space complexity is O ( n ) O(n) O ( n ) . Where n n n is the length of the array n u m s nums n u m s .
Note that the value of f [ i ] [ j ] f[i][j] f [ i ] [ j ] is only related to f [ i − 1 ] [ j ] f[i-1][j] f [ i − 1 ] [ j ] and f [ i − 1 ] [ ( j − x m o d 3 + 3 ) m o d 3 ] f[i-1][(j-x \bmod 3 + 3)\bmod 3] f [ i − 1 ] [( j − x mod 3 + 3 ) mod 3 ] , so we can use a rolling array to optimize the space complexity, reducing the space complexity to O ( 1 ) O(1) O ( 1 ) .
1
2
3
4
5
6
7
8
9
class Solution :
def maxSumDivThree ( self , nums : List [ int ]) -> int :
n = len ( nums )
f = [[ - inf ] * 3 for _ in range ( n + 1 )]
f [ 0 ][ 0 ] = 0
for i , x in enumerate ( nums , 1 ):
for j in range ( 3 ):
f [ i ][ j ] = max ( f [ i - 1 ][ j ], f [ i - 1 ][( j - x ) % 3 ] + x )
return f [ n ][ 0 ]
copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int maxSumDivThree ( int [] nums ) {
int n = nums . length ;
final int inf = 1 << 30 ;
int [][] f = new int [ n + 1 ][ 3 ] ;
f [ 0 ][ 1 ] = f [ 0 ][ 2 ] = - inf ;
for ( int i = 1 ; i <= n ; ++ i ) {
int x = nums [ i - 1 ] ;
for ( int j = 0 ; j < 3 ; ++ j ) {
f [ i ][ j ] = Math . max ( f [ i - 1 ][ j ] , f [ i - 1 ][ ( j - x % 3 + 3 ) % 3 ] + x );
}
}
return f [ n ][ 0 ] ;
}
}
copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public :
int maxSumDivThree ( vector < int >& nums ) {
int n = nums . size ();
const int inf = 1 << 30 ;
int f [ n + 1 ][ 3 ];
f [ 0 ][ 0 ] = 0 ;
f [ 0 ][ 1 ] = f [ 0 ][ 2 ] = - inf ;
for ( int i = 1 ; i <= n ; ++ i ) {
int x = nums [ i - 1 ];
for ( int j = 0 ; j < 3 ; ++ j ) {
f [ i ][ j ] = max ( f [ i - 1 ][ j ], f [ i - 1 ][( j - x % 3 + 3 ) % 3 ] + x );
}
}
return f [ n ][ 0 ];
}
};
copy
1
2
3
4
5
6
7
8
9
10
11
12
13
func maxSumDivThree ( nums [] int ) int {
n := len ( nums )
const inf = 1 << 30
f := make ([][ 3 ] int , n + 1 )
f [ 0 ] = [ 3 ] int { 0 , - inf , - inf }
for i , x := range nums {
i ++
for j := 0 ; j < 3 ; j ++ {
f [ i ][ j ] = max ( f [ i - 1 ][ j ], f [ i - 1 ][( j - x % 3 + 3 ) % 3 ] + x )
}
}
return f [ n ][ 0 ]
}
copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function maxSumDivThree ( nums : number []) : number {
const n = nums . length ;
const inf = 1 << 30 ;
const f : number [][] = Array ( n + 1 )
. fill ( 0 )
. map (() => Array ( 3 ). fill ( - inf ));
f [ 0 ][ 0 ] = 0 ;
for ( let i = 1 ; i <= n ; ++ i ) {
const x = nums [ i - 1 ];
for ( let j = 0 ; j < 3 ; ++ j ) {
f [ i ][ j ] = Math . max ( f [ i - 1 ][ j ], f [ i - 1 ][( j - ( x % 3 ) + 3 ) % 3 ] + x );
}
}
return f [ n ][ 0 ];
}
copy
Solution 2# 1
2
3
4
5
6
7
8
9
class Solution :
def maxSumDivThree ( self , nums : List [ int ]) -> int :
f = [ 0 , - inf , - inf ]
for x in nums :
g = f [:]
for j in range ( 3 ):
g [ j ] = max ( f [ j ], f [( j - x ) % 3 ] + x )
f = g
return f [ 0 ]
copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public int maxSumDivThree ( int [] nums ) {
final int inf = 1 << 30 ;
int [] f = new int [] { 0 , - inf , - inf };
for ( int x : nums ) {
int [] g = f . clone ();
for ( int j = 0 ; j < 3 ; ++ j ) {
g [ j ] = Math . max ( f [ j ] , f [ ( j - x % 3 + 3 ) % 3 ] + x );
}
f = g ;
}
return f [ 0 ] ;
}
}
copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public :
int maxSumDivThree ( vector < int >& nums ) {
const int inf = 1 << 30 ;
vector < int > f = { 0 , - inf , - inf };
for ( int & x : nums ) {
vector < int > g = f ;
for ( int j = 0 ; j < 3 ; ++ j ) {
g [ j ] = max ( f [ j ], f [( j - x % 3 + 3 ) % 3 ] + x );
}
f = move ( g );
}
return f [ 0 ];
}
};
copy
1
2
3
4
5
6
7
8
9
10
11
12
func maxSumDivThree ( nums [] int ) int {
const inf = 1 << 30
f := [ 3 ] int { 0 , - inf , - inf }
for _ , x := range nums {
g := [ 3 ] int {}
for j := range f {
g [ j ] = max ( f [ j ], f [( j - x % 3 + 3 ) % 3 ] + x )
}
f = g
}
return f [ 0 ]
}
copy
1
2
3
4
5
6
7
8
9
10
11
function maxSumDivThree ( nums : number []) : number {
const inf = 1 << 30 ;
const f : number [] = [ 0 , - inf , - inf ];
for ( const x of nums ) {
const g = [... f ];
for ( let j = 0 ; j < 3 ; ++ j ) {
f [ j ] = Math . max ( g [ j ], g [( j - ( x % 3 ) + 3 ) % 3 ] + x );
}
}
return f [ 0 ];
}
copy