求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
    评论
### 回答1: 可以使用递归的方法1+2+3+……+n的值。递归的思路是将问题分解为更小的子问题,直到问题可以被简单地解决。对于这个问题,我们可以将1+2+3+……+n分解为1+2+3+……+(n-1)和n两个子问题,然后递归地解这两个子问题,最后将它们的结果相加即可得到1+2+3+……+n的值。具体的递归函数可以成: def sum(n): if n == 1: return 1 else: return n + sum(n-1) 其中,当n等于1时,递归结束,返回1;否则,递归调用sum(n-1)解1+2+3+……+(n-1),然后将n加上这个结果得到1+2+3+……+n的值。 ### 回答2: 递归是一种很常见的编程方法,它在解决一些问题时,会把这个问题分解成若干个相似的子问题来解。递归函数就是在函数内部调用自身的函数。如果递归没有结束条件,就会进入无限递归,导致程序崩溃,因此递归一定要有适当的结束条件。 现在我们来看如何使用递归的方法1 2 3 …… n的值。 首先,我们需要定义一个函数,这个函数的功能就是给定一个n,出1 到 n的和。假设这个函数叫做sum,那么sum(n) = 1+2+3+...+n。 然后,我们需要确定递归结束的条件。显然,当n=1的时候,就只有一个数需要相加,此时sum(n)=1,这个时候递归就可以结束了。 接着,我们可以考虑如何使用递归的方式来解sum(n)。我们可以这么想:sum(n) = n + sum(n-1)。也就是说,n加上1 到 n-1的和,就等于1 到 n的和。而1 到 n-1的和,可以使用sum(n-1)来表示。然后,我们就可以用递归的方式解sum(n)了: sum(n) = sum(n-1) + n if n > 1 sum(n) = 1 if n = 1 把它转换成递归函数的形式如下: int sum(int n) { if(n == 1) return 1; //递归结束条件 else return sum(n-1) + n; //递归调用 } 以上是使用递归的方法解1 2 3 …… n的和,需要注意的是在进行递归过程中要注意递归深度的问题,如果递归的深度太大,程序就会崩溃,需要对递归深度进行限制和优化。 ### 回答3: 递归是常用的一种算法思想,它通过函数调用自身的方式解问题,可以很好地解决重复子问题的计算。在计算1,2,3,...,n的值时,递归是一种非常有效的方法。 递归函数的基本思路是:在函数内部调用自身来解决较小的子问题,直到子问题无法再分解,然后将各个子问题的结果进行合并得到最终结果。 具体实现时,可以定义一个递归函数recursion(n),计算1,2,3,...,n的值,其中n为递归函数的参数。当n等于1时,递归函数的返回值为1;当n大于1时,递归函数的返回值为n加上递归函数recursion(n-1)的返回值。 因此,递归函数recursion(n)的代码如下所示: ``` def recursion(n): if n == 1: return 1 else: return n + recursion(n-1) ``` 通过调用递归函数recursion(n),就可以出1,2,3,...,n的值。例如,当n等于5时,调用recursion(5)的返回值为15,即1+2+3+4+5=15。 需要注意的是,在使用递归算法时,需要注意递归深度不要太深,否则会造成栈溢出的问题。同时,为了避免重复计算,可以采用记忆化搜索等方法进行优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值