俄罗斯农民乘法

剑指 Offer 64 求1+2+…+n

题目

  • 求 1+2+…+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
  • 限制:1 <= n <= 10000

俄罗斯农民乘法

  • 又称快速乘法,对被乘数进行二进制展开后,基于加法实现乘法。由于计算机中位运算速度很快,所以效率很高。
  • 算法描述:对于A * B,如果 A / 2有余数,则把B累加到最后结果中,更新A = A / 2,B = B * 2。
    57 × 48 = 28 × 96 + 48 = 14 × 192 + 48 = 7 × 384 + 48 = 3 × 768 + 48 + 384 = 1 × 1536 + 48 + 384 + 768 \begin{aligned} 57 \times 48 & =28 \times 96+48 \\ & = 14 \times 192 + 48 \\ & = 7 \times 384 + 48 \\ & = 3 \times 768 + 48 + 384 \\ & = 1 \times 1536 + 48 + 384 + 768 \\ \end{aligned} 57×48=28×96+48=14×192+48=7×384+48=3×768+48+384=1×1536+48+384+768
  • 这里实际上是对57进行了二进制展开
    57 = 2 0 + 2 3 + 2 4 + 2 5 57 × 48 = ( 2 0 + 2 3 + 2 4 + 2 5 ) × 48 = 48 × 2 0 + 48 × 2 3 + 48 × 2 4 + 48 × 2 5 = 48 + 48 > > 1 + 48 > > 3 + 48 > > 4 + 48 > > 5 \begin{aligned} 57 & = 2^0 + 2^3 + 2^4 + 2^5 \\ 57 \times 48 & = ( 2^0 + 2^3 + 2^4 + 2^5 ) \times 48 \\ & = 48 \times 2^0 + 48 \times 2^3 + 48 \times 2^4 + 48 \times 2^5\\ & = 48 + 48>>1 + 48>>3 + 48>>4 + 48>>5 \end{aligned} 5757×48=20+23+24+25=(20+23+24+25)×48=48×20+48×23+48×24+48×25=48+48>>1+48>>3+48>>4+48>>5
function quickMultiple (A, B) {
    let res = 0
    while(A >= 1) {
        if (A & 1) {
            res += B
        }
        A>>1
        B<<1
    }
    return res
}

题解

1 + 2 + . . . + = ( 1 + n ) × n 2 = ( 1 + n ) × n > > 1 1 + 2 + ... + = \frac{(1 + n) \times n}{2} = (1 + n) \times n >>1 1+2+...+=2(1+n)×n=(1+n)×n>>1

  • 根据上述俄罗斯农民乘法,(1+n)*n = quickMultiple(1+n, n)
  • 但是,由于题目中要求不能使用while,所以接下来对quickMultiple进行改造:
    • 方法一:递归
    function quickMultipleRecrution (A, B) {
        if (A <= 1) {
            return 0
        }
    
    	// 这里其实相当于 const res = A & 1 ? B : 0
        const res = (A & 1) && B || 0
    
        return res + quickMultipleRecrution(A>>1, B<<1)
    }
    
    • 方法二:由于题目限制了n <= 1000 < 16384,二进制展开最多只有14位,所以手动模拟循环,进行14次的处理。
      • 记录官方题解
    function quickMultiple (A, B) {
        let res = 0;
        // 1
        (A & 1) && (res += B);
       	A >>= 1;
        B <<= 1;
        // 2
        (A & 1) && (res += B);
        A >>= 1;
        B <<= 1;
        // 3
        (A & 1) && (res += B);
        A >>= 1;
        B <<= 1;
        // 4
        (A & 1) && (res += B);
        A >>= 1;
        B <<= 1;
        // 5
        (A & 1) && (res += B);
        A >>= 1;
        B <<= 1;
        // 6
        (A & 1) && (res += B);
        A >>= 1;
        B <<= 1;
        // 7
        (A & 1) && (res += B);
        A >>= 1;
        B <<= 1;
        // 8
        (A & 1) && (res += B);
        A >>= 1;
        B <<= 1;
        // 9
        (A & 1) && (res += B);
        A >>= 1;
        B <<= 1;
        // 10
        (A & 1) && (res += B);
        A >>= 1;
        B <<= 1;
        // 11
        (A & 1) && (res += B);
        A >>= 1;
        B <<= 1;
        // 12
        (A & 1) && (res += B);
        A >>= 1;
        B <<= 1;
        // 13
        (A & 1) && (res += B);
        A >>= 1;
        B <<= 1;
        // 14
        (A & 1) && (res += B);
        A >>= 1;
        B <<= 1;
        return res
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值