题解 | #小红的数字删除#(Python3)

小红的数字删除

https://www.nowcoder.com/practice/46a73f7cb2ab4a56bdb372b282b23c1e

t = int(input())  # 读取测试用例的数量
for _ in range(0, t):  # 对每个测试用例进行处理
    s = input()  # 读取当前测试用例的正整数字符串
    n = len(s)  # 获取字符串的长度
    b = [0] * 4  # 初始化一个长度为4的数组,用于存储余数0, 1, 2, 3的个数
    ans = 0  # 初始化答案变量

    # 遍历字符串,统计每个数位模3的余数
    for i in range(0, n):
        m = ord(s[i]) - 48  # 将字符转换为对应的数字
        if(m != 0 and m % 3 == 0):  # 如果数字能被3整除且不为0
            b[3] += 1  # 增加余数为3的计数
        else:
            b[m % 3] += 1  # 增加对应余数的计数

    m = 0  # 用于计算所有数位模3的余数之和
    for i in range(1, 4):  # 计算1, 2, 3的余数之和
        m += i * b[i]

    # 如果余数之和不是3的倍数,则需要删除一些数位
    if(m % 3 != 0):
        if(b[m % 3] == 0):  # 如果没有余数为m%3的数位,则无法通过删除数位使数成为3的倍数
            print(0)
            continue
        ans += 1  # 增加删除操作次数
        b[m % 3] -= 1  # 减去一个余数为m%3的数位
        # 如果删除后没有余数为m%3的数位,且第一个数位的余数也是m%3,则需要特殊处理
        if(b[m % 3] == 0 and (ord(s[0]) - 48) % 3 == m % 3):
            if(b[0] == n - 1):  # 如果所有数位都是0,则无法通过删除数位使数成为3的倍数
                print(0)
                continue
            for i in range(1, n):  # 跳过前导0
                if(s[i] != '0'):
                    break
                b[0] -= 1
            if(b[1] == 0 and b[2] == 0):  # 如果没有余数为1或2的数位,则无法通过删除数位使数成为3的倍数
                ans -= 1

    # 答案包括所有余数为0的数位和所有能被3整除的数位
    ans += b[0] + b[3]
    # 答案不能超过n-1,因为至少需要保留一个数位
    ans = min(ans, n - 1)
    print(ans)

这里为什么不把输入的s直接转化为数字

在处理大数字时,直接将字符串str转换为数字可能会遇到一些问题:

  1. 数字大小限制:Python中的整数类型没有固定的大小限制,但是当数字非常大时,转换和操作这样的数字会消耗大量的内存和计算资源。
  2. 性能问题:对于非常大的数字,将字符串转换为整数可能会非常慢,特别是当这个操作需要在算法中重复多次时。
  3. 不必要的操作:如果我们的目标只是判断一个数字是否是3的倍数,或者需要删除最少数量的数位来使数字成为3的倍数,我们实际上不需要将整个数字作为整数来处理。我们只需要考虑每个数位的特性,即每个数位模3的余数。

在上述代码示例中,我们通过以下步骤来避免直接将整个字符串转换为数字:

  • 逐位处理:我们逐个处理字符串中的每个字符(即数字的每个数位),并计算它们模3的余数。这样可以避免处理整个大数字。
  • 计算余数和:通过计算所有数位模3的余数之和,我们可以判断整个数字是否是3的倍数,而不需要知道数字的具体值。
  • 优化删除操作:通过记录每个余数出现的次数,我们可以快速决定要删除哪些数位,以便使剩余的数字成为3的倍数。

综上所述,直接处理字符串而不是将字符串转换为数字可以优化算法的性能,特别是当处理非常大的数字时。此外,这种方法也更加灵活,因为它不依赖于数字的大小。

为什么要计算b和m,为什么用m%3来判断是否整个数字是3 的倍数

在这个问题中,我们想要判断一个数字是否是3的倍数,以及如果它不是3的倍数,我们需要删除最少数量的数位来使得剩下的数字是3的倍数。以下是bm的计算以及为什么使用m % 3来判断的详细解释:

  1. 计算b:b代表的是数字中所有数位模3的余数的总和。例如,如果数字是123,那么b将会是1%3 + 2%3 + 3%3的结果。这个计算是必要的,因为一个数字是3的倍数当且仅当它的所有数位之和是3的倍数。
  2. 计算m:m代表的是数字中每个数位模3的余数的个数。例如,如果数字是123,那么m将会是一个字典或列表,记录下余数为0的数位个数、余数为1的数位个数、余数为2的数位个数。这个计算有助于我们了解如何通过删除数位来使剩余的数字成为3的倍数。
  3. 使用m % 3来判断:当我们计算了所有数位模3的余数之和b之后,我们可以通过b % 3来判断b是否是3的倍数。如果b % 3的结果是0,那么原始数字就是3的倍数,我们不需要删除任何数位。如果b % 3的结果不是0,假设为r,那么我们需要删除一些数位来使得剩余的数位之和模3的结果为0。为了达到这个目的,我们可以删除余数为r的数位,因为删除这些数位会减少b中相应的余数总和,从而可能使剩余的数位之和成为3的倍数。
#15天刷题#
全部评论

相关推荐

点赞 评论 收藏
分享
01-14 19:01
吉首大学 Java
黑皮白袜臭脚体育生:加个项目吧,一般需要两个项目一业务一轮子呢,简历统一按使用了什么技术实现了什么功能解决了什么问题或提升了什么性能指标来写
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务