题解 | #小红的数字删除#(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
转换为数字可能会遇到一些问题:
- 数字大小限制:Python中的整数类型没有固定的大小限制,但是当数字非常大时,转换和操作这样的数字会消耗大量的内存和计算资源。
- 性能问题:对于非常大的数字,将字符串转换为整数可能会非常慢,特别是当这个操作需要在算法中重复多次时。
- 不必要的操作:如果我们的目标只是判断一个数字是否是3的倍数,或者需要删除最少数量的数位来使数字成为3的倍数,我们实际上不需要将整个数字作为整数来处理。我们只需要考虑每个数位的特性,即每个数位模3的余数。
在上述代码示例中,我们通过以下步骤来避免直接将整个字符串转换为数字:
- 逐位处理:我们逐个处理字符串中的每个字符(即数字的每个数位),并计算它们模3的余数。这样可以避免处理整个大数字。
- 计算余数和:通过计算所有数位模3的余数之和,我们可以判断整个数字是否是3的倍数,而不需要知道数字的具体值。
- 优化删除操作:通过记录每个余数出现的次数,我们可以快速决定要删除哪些数位,以便使剩余的数字成为3的倍数。
综上所述,直接处理字符串而不是将字符串转换为数字可以优化算法的性能,特别是当处理非常大的数字时。此外,这种方法也更加灵活,因为它不依赖于数字的大小。
为什么要计算b和m,为什么用m%3来判断是否整个数字是3 的倍数
在这个问题中,我们想要判断一个数字是否是3的倍数,以及如果它不是3的倍数,我们需要删除最少数量的数位来使得剩下的数字是3的倍数。以下是b
和m
的计算以及为什么使用m % 3
来判断的详细解释:
- 计算b:b代表的是数字中所有数位模3的余数的总和。例如,如果数字是123,那么b将会是1%3 + 2%3 + 3%3的结果。这个计算是必要的,因为一个数字是3的倍数当且仅当它的所有数位之和是3的倍数。
- 计算m:m代表的是数字中每个数位模3的余数的个数。例如,如果数字是123,那么m将会是一个字典或列表,记录下余数为0的数位个数、余数为1的数位个数、余数为2的数位个数。这个计算有助于我们了解如何通过删除数位来使剩余的数字成为3的倍数。
- 使用m % 3来判断:当我们计算了所有数位模3的余数之和b之后,我们可以通过b % 3来判断b是否是3的倍数。如果b % 3的结果是0,那么原始数字就是3的倍数,我们不需要删除任何数位。如果b % 3的结果不是0,假设为r,那么我们需要删除一些数位来使得剩余的数位之和模3的结果为0。为了达到这个目的,我们可以删除余数为r的数位,因为删除这些数位会减少b中相应的余数总和,从而可能使剩余的数位之和成为3的倍数。