LeetCode 题解工作台

形成三的最大倍数

给你一个整数数组 digits ,你可以通过按 任意顺序 连接其中某些数字来形成 3 的倍数,请你返回所能得到的最大的 3 的倍数。 由于答案可能不在整数数据类型范围内,请以字符串形式返回答案。如果无法得到答案,请返回一个空字符串。返回的结果不应包含不必要的前导零。 示例 1: 输入: digits…

category

5

题型

code_blocks

5

代码语言

hub

3

相关题

当前训练重点

困难 · 状态·转移·动态规划

bolt

答案摘要

我们定义 表示在前 个数中选取若干个数,使得选取的数的和模 为 的最大长度。为了使得选取的数最大,我们需要尽可能选取更多的数,因此我们需要使得 尽可能大。我们初始化 $f[0][0] = 0$,其余的 $f[0][j] = -\infty$。 考虑 如何进行状态转移。我们可以不选取第 个数,此时 $f[i][j] = f[i - 1][j]$;我们也可以选取第 个数,此时 $f[i…

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 状态·转移·动态规划 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给你一个整数数组 digits,你可以通过按 任意顺序 连接其中某些数字来形成 3 的倍数,请你返回所能得到的最大的 3 的倍数。

由于答案可能不在整数数据类型范围内,请以字符串形式返回答案。如果无法得到答案,请返回一个空字符串。返回的结果不应包含不必要的前导零。

 

示例 1:

输入:digits = [8,1,9]
输出:"981"

示例 2:

输入:digits = [8,6,7,1,0]
输出:"8760"

示例 3:

输入:digits = [1]
输出:""

示例 4:

输入:digits = [0,0,0,0,0,0]
输出:"0"

 

提示:

  • 1 <= digits.length <= 10^4
  • 0 <= digits[i] <= 9
lightbulb

解题思路

方法一:贪心 + 动态规划 + 逆推

我们定义 f[i][j]f[i][j] 表示在前 ii 个数中选取若干个数,使得选取的数的和模 33jj 的最大长度。为了使得选取的数最大,我们需要尽可能选取更多的数,因此我们需要使得 f[i][j]f[i][j] 尽可能大。我们初始化 f[0][0]=0f[0][0] = 0,其余的 f[0][j]=f[0][j] = -\infty

考虑 f[i][j]f[i][j] 如何进行状态转移。我们可以不选取第 ii 个数,此时 f[i][j]=f[i1][j]f[i][j] = f[i - 1][j];我们也可以选取第 ii 个数,此时 f[i][j]=f[i1][(jximod3+3)mod3]+1f[i][j] = f[i - 1][(j - x_i \bmod 3 + 3) \bmod 3] + 1,其中 xix_i 表示第 ii 个数的值。因此我们有如下的状态转移方程:

f[i][j]=max{f[i1][j],f[i1][(jximod3+3)mod3]+1}f[i][j] = \max \{ f[i - 1][j], f[i - 1][(j - x_i \bmod 3 + 3) \bmod 3] + 1 \}

如果 f[n][0]0f[n][0] \le 0,那么我们无法选取任何数,因此答案字符串为空。否则我们可以通过 ff 数组进行逆推,找出选取的数。

定义 i=ni = n, j=0j = 0,从 f[i][j]f[i][j] 开始逆推,记 k=(jximod3+3)mod3k = (j - x_i \bmod 3 + 3) \bmod 3,如果 f[i1][k]+1=f[i][j]f[i - 1][k] + 1 = f[i][j],那么我们选取了第 ii 个数,否则我们没有选取第 ii 个数。如果我们选取了第 ii 个数,那么我们将 jj 更新为 kk,否则我们保持 jj 不变。为了使得同等长度的数最大,我们应该优先选取较大的数,因此,我们在前面首先对数组进行排序。

时间复杂度 O(n×logn)O(n \times \log n),空间复杂度 O(n)O(n)。其中 nn 为数组的长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution:
    def largestMultipleOfThree(self, digits: List[int]) -> str:
        digits.sort()
        n = len(digits)
        f = [[-inf] * 3 for _ in range(n + 1)]
        f[0][0] = 0
        for i, x in enumerate(digits, 1):
            for j in range(3):
                f[i][j] = max(f[i - 1][j], f[i - 1][(j - x % 3 + 3) % 3] + 1)
        if f[n][0] <= 0:
            return ""
        arr = []
        j = 0
        for i in range(n, 0, -1):
            k = (j - digits[i - 1] % 3 + 3) % 3
            if f[i - 1][k] + 1 == f[i][j]:
                arr.append(digits[i - 1])
                j = k
        i = 0
        while i < len(arr) - 1 and arr[i] == 0:
            i += 1
        return "".join(map(str, arr[i:]))
speed

复杂度分析

指标
时间complexity is O(n + k log k) where n is the number of digits and k is the remaining digits after removal, mainly due to sorting. Space complexity is O(n) for storing grouped digits and intermediate states required by the state transition dynamic programming approach.
空间Depends on the final approach
psychology

面试官常问的追问

外企场景
  • question_mark

    Check if the sum of digits modulo three is zero to quickly identify multiples of three.

  • question_mark

    Consider edge cases with many zeros or a single digit that cannot form a multiple of three.

  • question_mark

    Verify your state transitions correctly remove minimal digits to maximize the final number.

warning

常见陷阱

外企场景
  • error

    Failing to remove the smallest number of digits needed, resulting in suboptimal output.

  • error

    Leaving unnecessary leading zeros in the final string.

  • error

    Ignoring digits classification by modulo three, which breaks the dynamic programming logic.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Find the smallest multiple of three instead of the largest, adjusting sorting strategy.

  • arrow_right_alt

    Return the largest multiple of five from digits using similar state transition reasoning.

  • arrow_right_alt

    Compute the largest multiple of k for any k using remainder-based dynamic programming extensions.

help

常见问题

外企场景

形成三的最大倍数题解:状态·转移·动态规划 | LeetCode #1363 困难