问题解析 :LeetCode 1006 "笨阶乘"要求对正整数 N 按递减顺序依次使用乘 *、除 /、加 +、减 - 四个运算符循环计算,即 clumsy(N) = N * (N-1) / (N-2) + (N-3) - (N-4) * (N-5) / (N-6) + ...,需返回计算结果。核心在于处理运算符优先级(乘除优先于加减)和循环模式。
解法对比:
| 方法 | 核心思路 | 时间复杂度 | 空间复杂度 | 适用场景 |
|---|---|---|---|---|
| 栈模拟 | 用栈存储中间结果,按运算符优先级处理 | O(N) | O(N) | 通用性强,直观模拟运算过程 |
| 数学归纳 | 观察规律,推导出分段计算公式 | O(1) | O(1) | 效率最高,直接计算 |
方法一:栈模拟法
通过栈保存待计算的值,遇到乘除立即计算,加减则入栈(减法转为加负数),最后对栈中所有元素求和。
cpp
#include <stack>
#include <vector>
using namespace std;
class Solution {
public:
int clumsy(int N) {
stack<int> stk;
stk.push(N);
N--;
int index = 0; // 用于循环运算符:0:*, 1:/, 2:+, 3:-
while (N > 0) {
if (index % 4 == 0) { // 乘法 int top = stk.top();
stk.pop();
stk.push(top * N);
} else if (index % 4 == 1) { // 除法 int top = stk.top();
stk.pop();
stk.push(top / N);
} else if (index % 4 == 2) { // 加法
stk.push(N);
} else { // 减法:转为加负数
stk.push(-N);
}
index++;
N--;
}
// 对栈中所有元素求和 int sum = 0;
while (!stk.empty()) {
sum += stk.top();
stk.pop();
}
return sum;
}
};
- 时间复杂度:O(N),遍历 N 次。
- 空间复杂度:O(N),栈最多存储约 N/2 个元素。
方法二:数学归纳法(O(1))
通过观察 N 较大时的计算规律,可发现每 4 个数一组 (N * (N-1) / (N-2) + (N-3))的结果近似为 N+1,剩余部分可推导出分段公式 :
- N ≤ 2:直接返回 N。
- N == 3 :返回
6(即3 * 2 / 1)。 - N == 4 :返回
7(即4 * 3 / 2 + 1)。 - N > 4 :
- 若
N % 4 == 0:结果为N + 1。 - 若
N % 4 == 1或N % 4 == 2:结果为N + 2。 - 若
N % 4 == 3:结果为N - 1。
- 若
cpp
class Solution {
public:
int clumsy(int N) {
if (N <= 2) return N;
if (N == 3) return 6;
if (N == 4) return 7;
// 根据 N 对 4 取余的结果返回对应值
if (N % 4 == 0) return N + 1;
if (N % 4 == 1 || N % 4 == 2) return N + 2;
return N - 1; // N % 4 == 3
}
};
- 时间复杂度:O(1)。
- 空间复杂度:O(1)。
推荐使用数学归纳法,其效率最高,代码简洁。栈模拟法虽直观,但效率较低,适用于需要严格模拟运算过程的场景。