华东师范大学2022年机试题中的"乘法"题目,看似简单实则暗藏玄机。作为计算机专业学生必须掌握的基础算法题,这道题考察的核心能力远超普通乘法运算本身。在实际编程竞赛和面试中,类似的大数乘法问题经常出现,因为它能全面检验考生的算法设计、边界处理以及代码优化能力。
这道题的特殊之处在于,它要求处理的数据规模远超常规。当两个超过计算机原生数据类型表示范围的大整数相乘时(比如两个100位的数字相乘),就不能简单地使用编程语言自带的乘法运算符了。这时候就需要我们手动实现一套完整的乘法算法,这也是这道题真正的考核重点。
处理大数乘法的第一步是确定如何存储这些超大整数。最直观的方法是用字符串来表示:
python复制num1 = "12345678901234567890"
num2 = "98765432109876543210"
字符串表示法的优点是可以处理任意长度的数字,不受编程语言整数类型范围的限制。但缺点是需要我们自己实现所有的算术运算。
对于大数乘法,最常用的算法是模拟手工竖式乘法。具体思路是:
这个算法的时间复杂度是O(n^2),其中n是数字的位数。虽然存在更高效的算法(如Karatsuba算法),但对于编程面试和考试场景,竖式乘法已经足够。
首先我们需要处理一些边界情况:
python复制if num1 == "0" or num2 == "0":
return "0"
然后可以创建一个足够大的数组来存储结果。两个n位数相乘,结果最多是2n位:
python复制result = [0] * (len(num1) + len(num2))
实现竖式乘法的核心代码如下:
python复制for i in range(len(num1)-1, -1, -1):
for j in range(len(num2)-1, -1, -1):
product = (ord(num1[i]) - ord('0')) * (ord(num2[j]) - ord('0'))
pos1, pos2 = i + j, i + j + 1
total = product + result[pos2]
result[pos1] += total // 10
result[pos2] = total % 10
这段代码做了以下几件事:
计算完成后,我们需要将结果数组转换为字符串,并去除可能的前导零:
python复制sb = []
for num in result:
if not sb and num == 0:
continue
sb.append(str(num))
return "".join(sb) if sb else "0"
将上述步骤组合起来,完整的Python实现如下:
python复制def multiply(num1: str, num2: str) -> str:
if num1 == "0" or num2 == "0":
return "0"
result = [0] * (len(num1) + len(num2))
for i in range(len(num1)-1, -1, -1):
for j in range(len(num2)-1, -1, -1):
product = (ord(num1[i]) - ord('0')) * (ord(num2[j]) - ord('0'))
pos1, pos2 = i + j, i + j + 1
total = product + result[pos2]
result[pos1] += total // 10
result[pos2] = total % 10
sb = []
for num in result:
if not sb and num == 0:
continue
sb.append(str(num))
return "".join(sb) if sb else "0"
虽然上述实现已经可以正确工作,但在实际编程竞赛中还可以进一步优化:
对于特别大的数字(比如超过10000位),可以考虑使用更高级的算法:
不过这些算法实现起来更复杂,通常只在处理极大数字时才需要。
大数乘法算法在实际中有广泛应用:
掌握这个算法不仅能帮助通过编程考试,也是后续学习更高级算法的基础。