数字字符串格式化| 豆包MarsCode AI 刷题

104 阅读4分钟

题目解析

给定一个数组 a,我们需要将数组中的数字分为两组,满足以下要求:

  1. 一组数字和的个位数等于 A(1 ≤ A ≤ 9)。
  2. 另一组数字和的个位数等于 B(1 ≤ B ≤ 9)。

或者

  • 其中一组为空,剩余数字和的个位数等于 A 或 B。

目标是求出所有满足上述条件的分组方式的数量。

解决思路

这个问题可以通过 动态规划(DP)来解决,核心思想是:我们关心的是数字的和的 个位数,而不是具体的数字本身。所以,我们可以使用 个位数的和 来构建状态,并通过 DP 来判断是否存在满足条件的分组。

分析过程

  1. 数字的个位数:首先,我们只关心每个数字的个位数。因为题目要求的是数字和的个位数,因此我们对每个数字取个位数,然后进行处理。

  2. 状态设计:设定一个 DP 状态 dp[i][j],表示使用前 i 个数字能否得到和的个位数为 j。我们一开始已经知道,和为 0 是可行的,因为我们可以选择空集。

  3. 状态转移

    • 对于每个数字 num,我们尝试将它加入已有的和中,然后更新新的状态。如果当前和为 j,加入数字 num 后新的和的个位数为 (j + num) % 10
  4. 目标:我们需要检查是否可以通过将数组中的元素分成两组,使得一组和的个位数为 A,另一组和的个位数为 B,或者某一组为空,剩下的数字和的个位数为 A 或 B。

特殊情况

  • 如果某一组为空,那么另一组的和的个位数必须等于 A 或 B。

解法步骤

  1. 计算所有数字的个位数:首先,我们对每个数字取个位数,将其转换为 nums[i] % 10

  2. 动态规划求解

    • 设定一个数组 dp,大小为 10,表示当前能达到的和的个位数(从 0 到 9)。
    • 初始时,dp[0] = 1,表示和为 0 是可行的(空集合)。
    • 对于每个数字 num,更新 dp 数组中的每个状态。
  3. 检查是否满足条件

    • 判断 dp[A] 和 dp[B],如果都为真,则表示可以分为两组,满足题意。
    • 如果只有一个组为空,检查其和的个位数是否为 A 或 B。

动态规划实现

pythonCopy Code
def countWays(nums, A, B):
    # 获取所有数字的个位数
    nums = [num % 10 for num in nums]
    
    # dp[i] 表示是否可以得到和为 i 的个位数
    dp = [0] * 10
    dp[0] = 1  # 和为 0 是可能的,表示空集

    # 动态规划更新 dp
    for num in nums:
        # 必须从后往前更新,避免重复计算
        new_dp = dp[:]
        for j in range(10):
            new_dp[(j + num) % 10] += dp[j]
        dp = new_dp
    
    # 总和的个位数
    total_sum = sum(nums) % 10
    
    # 如果 dp[A] 或 dp[B] 为 1,表示我们可以满足某一组和为 A 或 B
    result = dp[A] + dp[B]
    
    # 如果 total_sum 为 A 或 B,说明可以把一组设为空,剩余的和满足条件
    if total_sum == A or total_sum == B:
        result += 1
    
    return result

# 示例
nums = [1, 1, 1]
A = 1
B = 2
print(countWays(nums, A, B))  # 输出可能的分组方式数

代码解析

  1. 初始化

    • 我们先将所有的数字转换为个位数(通过 % 10 操作)。
    • 初始化 dp[0] = 1,表示和为 0 是可行的(空集合)。
  2. 动态规划

    • 我们通过循环遍历 nums 数组中的每个数字,并更新 dp 数组。注意要从后向前更新 dp,这样可以避免重复计算。
  3. 检查满足条件

    • 如果 dp[A] 或 dp[B] 为真,说明有一种分法满足条件。
    • 如果整个数组的和的个位数是 A 或 B,可以考虑一组为空的特殊情况。
  4. 返回结果

    • 返回 dp[A] + dp[B],表示有多少种满足条件的分法。
    • 如果数组总和的个位数是 A 或 B,额外加上 1 作为一种特殊情况(即另一组为空)。

时间复杂度与空间复杂度

  • 时间复杂度O(n * 10),其中 n 是数组的长度,10 是因为我们只关心个位数(0-9)。
  • 空间复杂度O(10),因为我们只需要一个大小为 10 的数组来存储状态。

总结

通过动态规划,我们能够有效地计算出满足题目要求的所有分组方式。核心思想是通过个位数来减少状态空间,并通过状态转移来判断是否能够找到符合条件的分组方式。