如何不用乘/除运算符递归相乘正整数?请解释给定递归实现
拆解minProduct递归乘法的逻辑
先补全这段代码的完整常规实现(你贴的内容截断了,这是符合需求的完整版本):
def minProduct(a,b): bigger = b if a < b else a smaller = a if a < b else b return minProductHelper(smaller, bigger) def minProductHelper(smaller, bigger): if smaller == 0: return 0 if smaller == 1: return bigger # 用位运算把smaller分成一半(等价于正整数的整数除法除以2) s = smaller >> 1 half_prod = minProductHelper(s, bigger) if smaller % 2 == 0: return half_prod + half_prod else: return half_prod + half_prod + bigger
第一步:先分大小的小优化
主函数里的bigger和smaller赋值是个实用的小技巧:我们把两个数里更小的那个作为递归的「拆分基准」,这样能大幅减少递归的层数。比如算3*100,用smaller=3递归只需要3层;如果反过来用100当基准,递归次数会多得多,这一步是为了让递归更高效。
第二步:递归核心——完全贴合你的「网格翻倍」思路
这段代码的本质就是分治思想,和你理解的「计算a*b网格的一半单元格再翻倍」完全对应:
- 把
smaller看作网格的行数,bigger看作列数,总单元格数就是我们要的乘积smaller*bigger。 - 我们不断把行数拆成两半,再把拆分后的结果组合起来:
- 如果行数是偶数:比如4行,直接分成两个2行的网格,总单元格数就是「2行网格的数量 + 2行网格的数量」,也就是
half_prod + half_prod。 - 如果行数是奇数:比如5行,分成两个2行的网格后,还多出来1行,总数量就是「两个2行网格的数量 + 额外1行的单元格数(也就是
bigger)」,也就是half_prod + half_prod + bigger。
- 如果行数是偶数:比如4行,直接分成两个2行的网格,总单元格数就是「2行网格的数量 + 2行网格的数量」,也就是
递归的终止条件(Base Case)
- 当
smaller是0:0乘以任何数都是0,对应「0行网格没有单元格」,直接返回0。 - 当
smaller是1:1乘以任何数就是那个数本身,对应「1行网格的单元格数就是列数」,直接返回bigger。
位运算的作用
代码里用smaller >> 1代替除法,是因为题目不让用*或/运算符。对正整数来说,位运算右移一位完全等价于整数除法除以2(比如5>>1=2,4>>1=2),刚好满足我们拆分行数的需求。
举个具体例子,算5*7:
- 初始
smaller=5,bigger=7 s=5>>1=2,递归计算2*7- 计算
2*7时,s=2>>1=1,递归到1*7,返回7 2是偶数,所以2*7=7+7=14- 回到
5*7,5是奇数,结果就是14+14+7=35,正好是5*7的乘积。
内容的提问来源于stack exchange,提问作者Utkarsh Prakash
相关产品推荐
相关产品推荐

