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

本文介绍了一种不使用常规控制结构的求1+2+...+n的方法,通过巧妙利用逻辑运算符实现了递归求和,并提供了一种基于位操作的快速乘法算法来优化计算效率。

题目链接:leetcode.

好可爱啊这个题,断了我所有的后路

要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)

难道是递归?

class Solution {
public:
    int sumNums(int n) {
        return n + ((n-1) && sumNums(n - 1)); 
        //不对的,逻辑与得到的不是1就是0 
    }
};

看题解( ̄▽ ̄)"
其实我们想要返回的是n ? n +sumNums(n - 1) : 0 ,又已知

A && B,当A为真才执行B
A || B,当A为假才执行B

所以修改可得

n && (n = n + sumNUms(n - 1))
n || n = 0 省略

时间复杂度O(n)、空间复杂度O(n)

/*
执行用时:4 ms, 在所有 C++ 提交中击败了28.64%的用户
内存消耗:6.1 MB, 在所有 C++ 提交中击败了54.20%的用户
*/
class Solution {
public:
    int sumNums(int n) {
    	n && (n = n + sumNums(n - 1));
        return n; 
    }
};

我佛了,第一次听到这种,快速乘的方法诶

十进制 88*99 = 88 * 9 * 10^0 + 88 * 9 * 10^1
那么二进制表示的话就是 
88 * 0110 0011	  = 88 * 0 * 2^7 
                  + 88 * 1 * 2^6 
                  + 88 * 1 * 2^5 
                  + 88 * 0 * 2^4 
                  + 88 * 0 * 2^3 
                  + 88 * 0 * 2^2 
                  + 88 * 1 * 2^1
                  + 88 * 1 * 2^0  

对于A * B,如果B的第 i位为1,其对乘积的贡献就是 A * 1 * 2^i,也就是A << i,循环实现如下:

int quickMulti(int A, int B) {
    int ans = 0;
    for ( ; B; B >>= 1) {
        if (B & 1) {
            ans += A;
        }
        A <<= 1;
    }
    return ans;
}

//作者:LeetCode-Solution
//链接:https://leetcode-cn.com/problems/qiu-12n-lcof/solution/qiu-12n-by-leetcode-solution/
//来源:力扣(LeetCode)
//著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

对本题而言,所求的和可以用等差数列求和公式表示为 (n * (n + 1))/2,即(n * (n + 1))>>1,再计算 (n * (n + 1))的快速乘,但不能用循环,奥杜剋ฅʕ•̫͡•ʔฅ
本题限制了1 <= n <= 10000,所以我们可以手动重复14遍!

/*
执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:5.7 MB, 在所有 C++ 提交中击败了99.10%的用户
*/
class Solution {
public:
    int sumNums(int n) {
    	int A = n + 1, B = n;
		int ans = 0;
		//十四遍!
		B && (B & 1) && (ans += A);//考虑到运算符的优先级,就用括号吧
		B >>= 1;
		A <<= 1; 
		
		B && (B & 1) && (ans += A);
		B >>= 1;
		A <<= 1; 
		
		B && (B & 1) && (ans += A);
		B >>= 1;
		A <<= 1; 
		
		B && (B & 1) && (ans += A);
		B >>= 1;
		A <<= 1; 
		
		B && (B & 1) && (ans += A);
		B >>= 1;
		A <<= 1; 
		
		B && (B & 1) && (ans += A);
		B >>= 1;
		A <<= 1; 
		
		B && (B & 1) && (ans += A);
		B >>= 1;
		A <<= 1; 
		
		B && (B & 1) && (ans += A);
		B >>= 1;
		A <<= 1; 
		
		B && (B & 1) && (ans += A);
		B >>= 1;
		A <<= 1; 
		
		B && (B & 1) && (ans += A);
		B >>= 1;
		A <<= 1; 
		
		B && (B & 1) && (ans += A);
		B >>= 1;
		A <<= 1; 
		
		B && (B & 1) && (ans += A);
		B >>= 1;
		A <<= 1; 
		
		B && (B & 1) && (ans += A);
		B >>= 1;
		A <<= 1; 
		
		B && (B & 1) && (ans += A);
		B >>= 1;
		A <<= 1; 
		
		return ans>>1;
    }
};
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值