48
48
49
49
** 方法一:动态规划**
50
50
51
- 我们定义 $f[ j] $ 表示前 $i-1$ 个数中,余数为 $j$ 的最大和。那么对于当前的数 $x$,我们可以将其加入到前面的数中,得到的和为 $f[ j ] + x$,其中 $j$ 为 $(f [ j ] + x) \bmod 3 $。
51
+ 我们定义 $f[ i ] [ j ] $ 表示前 $i$ 个数中选取若干个数,使得这若干个数的和模 $3$ 余 $j$ 的最大值。初始时 $f[ 0 ] [ 0 ] =0$,其余为 $-\infty $。
52
52
53
- 最后,我们返回 $f[ 0 ] $ 即可。
53
+ 对于 $f[ i ] [ j ] $,我们可以考虑第 $i$ 个数 $x$ 的状态:
54
54
55
- 时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 ` nums ` 的长度。
55
+ - 如果我们不选 $x$,那么 $f[ i] [ j ] =f[ i-1] [ j ] $;
56
+ - 如果我们选 $x$,那么 $f[ i] [ j ] =f[ i-1] [ (j-x \bmod 3 + 3)\bmod 3 ] +x$。
57
+
58
+ 因此我们可以得到状态转移方程:
59
+
60
+ $$
61
+ f[i][j]=\max\{f[i-1][j],f[i-1][(j-x \bmod 3 + 3)\bmod 3]+x\}
62
+ $$
63
+
64
+ 最终答案为 $f[ n] [ 0 ] $。
65
+
66
+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $nums$ 的长度。
67
+
68
+ 注意到 $f[ i] [ j ] $ 的值只与 $f[ i-1] [ j ] $ 和 $f[ i-1] [ (j-x \bmod 3 + 3)\bmod 3 ] $ 有关,因此我们可以使用滚动数组优化空间复杂度,使空间复杂度降低为 $O(1)$。
56
69
57
70
<!-- tabs:start -->
58
71
63
76
``` python
64
77
class Solution :
65
78
def maxSumDivThree (self , nums : List[int ]) -> int :
66
- f = [0 ] * 3
79
+ n = len (nums)
80
+ f = [[- inf] * 3 for _ in range (n + 1 )]
81
+ f[0 ][0 ] = 0
82
+ for i, x in enumerate (nums, 1 ):
83
+ for j in range (3 ):
84
+ f[i][j] = max (f[i - 1 ][j], f[i - 1 ][(j - x) % 3 ] + x)
85
+ return f[n][0 ]
86
+ ```
87
+
88
+ ``` python
89
+ class Solution :
90
+ def maxSumDivThree (self , nums : List[int ]) -> int :
91
+ f = [0 , - inf, - inf]
67
92
for x in nums:
68
- a, b, c = f[0 ] + x, f[ 1 ] + x, f[ 2 ] + x
69
- f[a % 3 ] = max (f[a % 3 ], a)
70
- f[b % 3 ] = max (f[b % 3 ], b )
71
- f[c % 3 ] = max (f[c % 3 ], c)
93
+ g = f[:]
94
+ for j in range ( 3 ):
95
+ g[j ] = max (f[j], f[(j - x) % 3 ] + x )
96
+ f = g
72
97
return f[0 ]
73
98
```
74
99
@@ -79,12 +104,32 @@ class Solution:
79
104
``` java
80
105
class Solution {
81
106
public int maxSumDivThree (int [] nums ) {
82
- int [] f = new int [3 ];
107
+ int n = nums. length;
108
+ final int inf = 1 << 30 ;
109
+ int [][] f = new int [n + 1 ][3 ];
110
+ f[0 ][1 ] = f[0 ][2 ] = - inf;
111
+ for (int i = 1 ; i <= n; ++ i) {
112
+ int x = nums[i - 1 ];
113
+ for (int j = 0 ; j < 3 ; ++ j) {
114
+ f[i][j] = Math . max(f[i - 1 ][j], f[i - 1 ][(j - x % 3 + 3 ) % 3 ] + x);
115
+ }
116
+ }
117
+ return f[n][0 ];
118
+ }
119
+ }
120
+ ```
121
+
122
+ ``` java
123
+ class Solution {
124
+ public int maxSumDivThree (int [] nums ) {
125
+ final int inf = 1 << 30 ;
126
+ int [] f = new int [] {0 , - inf, - inf};
83
127
for (int x : nums) {
84
- int a = f[0 ] + x, b = f[1 ] + x, c = f[2 ] + x;
85
- f[a % 3 ] = Math . max(f[a % 3 ], a);
86
- f[b % 3 ] = Math . max(f[b % 3 ], b);
87
- f[c % 3 ] = Math . max(f[c % 3 ], c);
128
+ int [] g = f. clone();
129
+ for (int j = 0 ; j < 3 ; ++ j) {
130
+ g[j] = Math . max(f[j], f[(j - x % 3 + 3 ) % 3 ] + x);
131
+ }
132
+ f = g;
88
133
}
89
134
return f[0 ];
90
135
}
@@ -97,12 +142,34 @@ class Solution {
97
142
class Solution {
98
143
public:
99
144
int maxSumDivThree(vector<int >& nums) {
100
- int f[ 3] {};
101
- for (int x : nums) {
102
- int a = f[ 0] + x, b = f[ 1] + x, c = f[ 2] + x;
103
- f[ a % 3] = max(f[ a % 3] , a);
104
- f[ b % 3] = max(f[ b % 3] , b);
105
- f[ c % 3] = max(f[ c % 3] , c);
145
+ int n = nums.size();
146
+ const int inf = 1 << 30;
147
+ int f[ n + 1] [ 3 ] ;
148
+ f[ 0] [ 0 ] = 0;
149
+ f[ 0] [ 1 ] = f[ 0] [ 2 ] = -inf;
150
+ for (int i = 1; i <= n; ++i) {
151
+ int x = nums[ i - 1] ;
152
+ for (int j = 0; j < 3; ++j) {
153
+ f[ i] [ j ] = max(f[ i - 1] [ j ] , f[ i - 1] [ (j - x % 3 + 3) % 3 ] + x);
154
+ }
155
+ }
156
+ return f[ n] [ 0 ] ;
157
+ }
158
+ };
159
+ ```
160
+
161
+ ```cpp
162
+ class Solution {
163
+ public:
164
+ int maxSumDivThree(vector<int>& nums) {
165
+ const int inf = 1 << 30;
166
+ vector<int> f = {0, -inf, -inf};
167
+ for (int& x : nums) {
168
+ vector<int> g = f;
169
+ for (int j = 0; j < 3; ++j) {
170
+ g[j] = max(f[j], f[(j - x % 3 + 3) % 3] + x);
171
+ }
172
+ f = move(g);
106
173
}
107
174
return f[0];
108
175
}
@@ -113,12 +180,37 @@ public:
113
180
114
181
``` go
115
182
func maxSumDivThree (nums []int ) int {
116
- f := [3]int{}
183
+ n := len (nums)
184
+ const inf = 1 << 30
185
+ f := make ([][3 ]int , n+1 )
186
+ f[0 ] = [3 ]int {0 , -inf, -inf}
187
+ for i , x := range nums {
188
+ i++
189
+ for j := 0 ; j < 3 ; j++ {
190
+ f[i][j] = max (f[i-1 ][j], f[i-1 ][(j-x%3 +3 )%3 ]+x)
191
+ }
192
+ }
193
+ return f[n][0 ]
194
+ }
195
+
196
+ func max (a , b int ) int {
197
+ if a > b {
198
+ return a
199
+ }
200
+ return b
201
+ }
202
+ ```
203
+
204
+ ``` go
205
+ func maxSumDivThree (nums []int ) int {
206
+ const inf = 1 << 30
207
+ f := [3 ]int {0 , -inf, -inf}
117
208
for _ , x := range nums {
118
- a, b, c := f[0]+x, f[1]+x, f[2]+x
119
- f[a%3] = max(f[a%3], a)
120
- f[b%3] = max(f[b%3], b)
121
- f[c%3] = max(f[c%3], c)
209
+ g := [3 ]int {}
210
+ for j := range f {
211
+ g[j] = max (f[j], f[(j-x%3 +3 )%3 ]+x)
212
+ }
213
+ f = g
122
214
}
123
215
return f[0 ]
124
216
}
@@ -131,6 +223,43 @@ func max(a, b int) int {
131
223
}
132
224
```
133
225
226
+ ### ** TypeScript**
227
+
228
+ ``` ts
229
+ function maxSumDivThree(nums : number []): number {
230
+ const n = nums .length ;
231
+ const inf = 1 << 30 ;
232
+ const f: number [][] = Array (n + 1 )
233
+ .fill (0 )
234
+ .map (() => Array (3 ).fill (- inf ));
235
+ f [0 ][0 ] = 0 ;
236
+ for (let i = 1 ; i <= n ; ++ i ) {
237
+ const x = nums [i - 1 ];
238
+ for (let j = 0 ; j < 3 ; ++ j ) {
239
+ f [i ][j ] = Math .max (
240
+ f [i - 1 ][j ],
241
+ f [i - 1 ][(j - (x % 3 ) + 3 ) % 3 ] + x ,
242
+ );
243
+ }
244
+ }
245
+ return f [n ][0 ];
246
+ }
247
+ ```
248
+
249
+ ``` ts
250
+ function maxSumDivThree(nums : number []): number {
251
+ const inf = 1 << 30 ;
252
+ const f: number [] = [0 , - inf , - inf ];
253
+ for (const x of nums ) {
254
+ const g = [... f ];
255
+ for (let j = 0 ; j < 3 ; ++ j ) {
256
+ f [j ] = Math .max (g [j ], g [(j - (x % 3 ) + 3 ) % 3 ] + x );
257
+ }
258
+ }
259
+ return f [0 ];
260
+ }
261
+ ```
262
+
134
263
### ** ...**
135
264
136
265
```
0 commit comments