问题描述
递归实现
void hanoi_recursively(int n, char from, char via, char to) {
if (n == 1) {
printf("%c -> %c\n", from, to);
} else {
hanoi_recursively(n - 1, from, to, via);
hanoi_recursively(1, from, via, to);
hanoi_recursively(n - 1, via, from, to);
}
}
非递归实现
#include <stack>
#include <stdio.h>
using namespace std;
struct Problem {
int n;
char from, via, to;
Problem (int nn, char f, char v, char t) : n(nn), from(f), via(v), to(t) {}
};
int main() {
int N;
scanf("%d", &N);
stack<Problem> stk;
stk.push(Problem(N, 'a', 'b', 'c'));
while(!stk.empty()) {
Problem p = stk.top();
stk.pop();
if (p.n == 1) {
printf("%c -> %c\n", p.from, p.to);
} else {
//注意这里的压栈顺序和递归求解时是相反的
stk.push(Problem(p.n - 1, p.via, p.from, p.to));
stk.push(Problem(1, p.from, p.via, p.to));
stk.push(Problem(p.n - 1, p.from, p.to, p.via));
}
}
return 0;
}
问题解答
牛客网:
#include <vector>
class Solution {
public:
void hanoi(int n, string from, string via, string to, vector<string>& res) {
if (n == 1) {
res.push_back("move from " + from + " to " + to);
} else {
hanoi(n - 1, from, to, via, res);
hanoi(1, from, via, to, res);
hanoi(n - 1, via, from, to, res);
}
}
vector<string> getSolution(int n) {
// write code here
vector<string> res;
hanoi(n, "left", "mid", "right", res);
return res;
}
};
百练:
#include <stdio.h>
using namespace std;
void hanoi(int n, char from, char via, char to, int id) {
if (n == 1) {
printf("%d:%c->%c\n", id, from, to);
} else {
hanoi(n - 1, from, to, via, n - 1);
hanoi(1, from, via, to, n); //问题的规模=最后一个盘子的编号
hanoi(n - 1, via, from, to, n - 1);
}
}
int main() {
char a, b, c;
int n;
scanf("%d %c %c %c", &n, &a, &b, &c);
hanoi(n, a, b, c, n);
return 0;
}
PTA:参考上方的“非递归实现”
复杂度分析
假设有n片,移动次数是f(n),显然f(1)=1,f(2)=3,f(3)=7
根据递归结构有: f ( k + 1 ) = 2 ∗ f ( k ) + 1 f(k + 1) = 2*f(k) + 1 f(k+1)=2∗f(k)+1,下面求解这个递归式:
f ( k + 1 ) + 1 = 2 ∗ ( f ( k ) + 1 ) f(k + 1) + 1 = 2*(f(k) + 1) f(k+1)+1=2∗(f(k)+1)
于是:
f ( k + 1 ) + 1 f ( k ) + 1 = 2 \frac{f(k + 1) + 1 }{f(k) + 1} = 2 f(k)+1f(k+1)+1=2
则 f ( k ) + 1 f(k) + 1 f(k)+1为等比数列,于是 f ( k ) = 2 k − 1 f(k) = 2^k - 1 f(k)=2k−1
所以汉诺塔问题的时间复杂度和空间复杂度均为 O ( 2 n ) O(2^n) O(2n)