剑指 Offer 64. 求1+2+…+n
求 1+2+…+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
示例 1:
输入: n = 3
输出: 6
示例 2:
输入: n = 9
输出: 45
限制:
1 <= n <= 10000
class Solution {
public int sumNums(int n) {
Boolean b= n>0 && (n+=sumNums(n-1))>0;
return n;
}
}
通常实现递归的时候,我们都会利用条件判断语句来决定递归的出口,但由于题目的限制我们不能使用条件判断语句,那么我们是否能使用别的办法来确定递归出口呢?
- 答案就是逻辑运算符的短路性质。
-
以逻辑运算符 && 为例,对于 A && B 这个表达式,如果 A 表达式返回 False ,那么 A && B 已经确定为False ,此时不会去执行表达式 B。同理,对于逻辑运算符 ||, 对于 A || B 这个表达式,如果 A 表达式返回 True ,那么 A || B 已经确定为True ,此时不会去执行表达式 B。
-
利用这一特性,我们可以将判断是否为递归的出口看作 A && B 表达式中的 A 部分,递归的主体函数看作 B 部分。如果不是递归出口,则返回True,并继续执行表达式 B 的部分,否则递归结束。
当然,你也可以用逻辑运算符 || 给出类似的实现,如下方代码所示。
class Solution {
public int sumNums(int n) {
Boolean b= n<=0 || (n+=sumNums(n-1))<0;
return n;
}
}
复杂度分析
- 时间复杂度:O(n)。递归函数递归 n 次,每次递归中的时间复杂度为O(1),因此总时间复杂度为O(n)*Q(1)=O(n)
- 空间复杂度:O(n)。递归函数的空间复杂度取决于递归调用栈的深度,这里递归函数调用栈深度为O(n),因此空间复杂度为O(N)
参考:https://leetcode-cn.com/problems/qiu-12n-lcof/solution/qiu-12n-by-leetcode-solution/