求1+2+3+……+n

题目描述

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

分析:这道题可谓是反人类了,不让用的东西也忒多了,本来乘除就能解决的事情,不让用乘除递归或者循环也可以,偏偏for、if之类的不让用,那么我们想要解决这个问题,就需要想到一种不用if等判断语句也能终止的条件,比较简单的便是短路。这个算法很精妙,不过要是有大神像剑指offer上那样用虚函数来解决这个问题也是可以的,下面会放上剑指offer的代码。当然还有些比较有趣的思路,一种是开辟n*(n+1)个字节的空间然后用sizeof的,还有一种更暴力的,不让我用乘法,我就用快速幂,不让我用循环,我就复制32遍!!!这个人比较狠,是一位叫做马客(Mark)的大佬,代码会贴在下面。

代码:利用短路实现递归终止条件,个人比较推荐这种做法

class Solution {
public:
    int Sum_Solution(int n) {
        int res=n;
        n&&(res+=Sum_Solution(n-1));
        return res;
    }
};

然后是剑指offer上的做法,剑指offer上有四种,这里只列了三种,剩下那种也是虚函数,差不多就没贴

链接:https://www.nowcoder.com/questionTerminal/7a0da8fc483247ff8800059e12d7caf1
来源:牛客网

class assist{
public :
    assist() {N++;sum += N;}
    static void reset(){N=0;sum=0;} //在VS中不需要此调用函数也可以(不进行多加一次)
    static unsigned int GetSum(){ return sum;}
private :
    static int N;
    static int sum;
};
int assist::N = 0;
int assist::sum = 0;
//设置一个静态变量N和sum,在构造函数中进行累加运算;
//然后构造一个以辅助类为类型、大小为n的数组,重复调用此构造函数n次来实现n次的累加运算
class Solution {
public :
    int Sum_Solution( int n) {
        assist::reset();
        assist * p = new assist[n];
        delete []p;
        p = nullptr;
        return assist::GetSum();
    }
};
//第二种方法:使用模板函数进行编程,显示定义输入参数为1的模块
    template < int m> inline int SumTo() { return m + SumTo<m-1>(); }  template <> inline int SumTo<1>() { return 1; }
//第三种方法:使用虚函数
 
     class Base;
Base* Array[2];
class Base{
public :
      virtual int Sum( int n){ return 0;}
};
class Derived : public Base{
public :
    virtual int Sum( int n){ return Array[!!n]->Sum(n-1) + n;}
     
};
//使用虚函数来构造递归,在基类种定义虚函数Sum(n)返回0,通过将指针数组的两个元素分别绑定到基类和派生类,其中基类的Sum()
//结束递归,!!n来构造true(1) false(0)来对指针数组进行访问
class Solution {
public :
    int Sum_Solution( int n) {
        Base a;
        Derived b;
        Array[0] = &a;
        Array[1] = &b;
        return b.Sum(n);
    }
};
然后下面就是一些大神放飞自我的时间了,先贴的是利用sizeof的,后贴的是复制32遍的

链接:https://www.nowcoder.com/questionTerminal/7a0da8fc483247ff8800059e12d7caf1
来源:牛客网

class Solution {
public :
     int Sum_Solution( int n) {
         bool a[n][n+1];
         return sizeof (a)>>1;
     }
};

链接:https://www.nowcoder.com/questionTerminal/7a0da8fc483247ff8800059e12d7caf1
来源:牛客网

我就猜到大家都是用 && 的短路原则的,这样复杂是O(n)的
我来一个复杂度 32的,可以说O(logM)吧,M是数值大小,对于int也可以说是O(1)吧虽然常数有点大。
原理就是,类似快速幂,俗称快速模乘。
a * b
可以这样算
1
2
3
4
5
6
res = 0
while (a){
    if (a & 1) res += b;
    a >>= 1;
    b <<= 1; 
}
原理是把a拆成2的幂的和,a = 2^e0 + 2^e1 + 2^e2....
那么 a * b = (2^e0 + 2^e1 + 2^e2+...) * b = b * 2^e0 + b * 2^e1 + b * 2^e2 + ...
= (b << e0) + (b << e1) + ....

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//奇数返回0xffffffff,否则0
#define f(x) ((((x) & 1) << 31) >> 31)
class Solution {
public :
    int Sum_Solution( int n) {
        int a = n, b = n + 1, s = 0;
        //复制32次。。
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
         
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
         
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
         
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        s += b & f(a); a >>= 1; b <<= 1;
        return s >> 1;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值