classSolution: defmaxSumDivThree(self, nums: List[int]) -> int: self.res = 0 defbacktrack(temp, start): total = sum(temp) if total % 3 == 0: self.res = max(self.res, total) for i in range(start, len(nums)): temp.append(nums[i]) backtrack(temp, i + 1) temp.pop(-1)
backtrack([], 0)
return self.res
减法 + 排序
减法的核心思想是,我们求出总和。如果总和不满足题意,我们尝试减去最小的数,使之满足题意。
思路
这种算法的思想,具体来说就是:
我们将所有的数字加起来,我们不妨设为 total
total 除以 3,得到一个余数 mod, mod 可能值有 0,1,2.
同时我们建立两个数组,一个是余数为 1 的数组 one,一个是余数为 2 的数组 two
如果 mod 为 0,我们直接返回即可。
如果 mod 为 1,我们可以减去 one 数组中最小的一个(如果有的话),或者减去两个 two 数组中最小的(如果有的话),究竟减去谁取决谁更小。
如果 mod 为 2,我们可以减去 two 数组中最小的一个(如果有的话),或者减去两个 one 数组中最小的(如果有的话),究竟减去谁取决谁更小。
由于我们需要取 one 和 two 中最小的一个或者两个,因此对数组 one 和 two 进行排序是可行的,如果基于排序的话,时间复杂度大致为 $O(NlogN)$,这种算法可以通过。
classSolution: defmaxSumDivThree(self, nums: List[int]) -> int: one = [] two = [] total = 0
for num in nums: total += num if num % 3 == 1: one.append(num) if num % 3 == 2: two.append(num) one.sort() two.sort() if total % 3 == 0: return total elif total % 3 == 1and one: if len(two) >= 2and one[0] > two[0] + two[1]: return total - two[0] - two[1] return total - one[0] elif total % 3 == 2and two: if len(one) >= 2and two[0] > one[0] + one[1]: return total - one[0] - one[1] return total - two[0] return0
减法 + 非排序
思路
上面的解法使用到了排序。 我们其实观察发现,我们只是用到了 one 和 two 的最小的两个数。因此我们完全可以在线形的时间和常数的空间完成这个算法。我们只需要分别记录 one 和 two 的最小值和次小值即可,在这里,我使用了两个长度为 2 的数组来表示,第一项是最小值,第二项是次小值。
classSolution: defmaxSumDivThree(self, nums: List[int]) -> int: one = [float('inf')] * 2 two = [float('inf')] * 2 total = 0
for num in nums: total += num if num % 3 == 1: if num < one[0]: t = one[0] one[0] = num one[1] = t elif num < one[1]: one[1] = num if num % 3 == 2: if num < two[0]: t = two[0] two[0] = num two[1] = t elif num < two[1]: two[1] = num if total % 3 == 0: return total elif total % 3 == 1and one: if len(two) >= 2and one[0] > two[0] + two[1]: return total - two[0] - two[1] return total - one[0] elif total % 3 == 2and two: if len(one) >= 2and two[0] > one[0] + one[1]: return total - one[0] - one[1] return total - two[0] return0
for num in nums: if num % 3 == 0: state = [state[0] + num, state[1] + num, state[2] + num] if num % 3 == 1: a = max(state[2] + num, state[0]) b = max(state[0] + num, state[1]) c = max(state[1] + num, state[2]) state = [a, b, c] if num % 3 == 2: a = max(state[1] + num, state[0]) b = max(state[2] + num, state[1]) c = max(state[0] + num, state[2]) state = [a, b, c] return state[0]