一、汉诺塔问题
1.问题描述
有a、b、c三个塔柱,8个圆盘在塔柱a上,大小随高度增加而减小,将8个圆盘从塔柱a移动到塔柱b,遵循以下规则:
- 每次只移动一个圆盘
- 不允许将大圆盘移动到小圆盘之上
2.问题框架
在用递归解决此问题时,递归程序应包含以下参数:
- 需要移动圆盘数量
- 开始的塔柱名字
- 最终所在的塔柱名字
- 临时储存圆盘的塔柱名字
据此得到如下函数原型:
void moveTower(int n, char start, char finish, char tmp);
3.递归策略
- 将最上面的N-1个圆盘从开始所在的塔柱移动到临时塔柱上
- 将最底下的一个圆盘从开始所在的塔柱移动到最终所在塔柱上
- 将N-1个圆盘从临时塔柱移回到最终所在塔柱上
4.编码方案
操作输出函数:
void moveSingleDisk(char start, char finish) {
cout << strat << "->" << finish << endl;
}
具体实现函数:
void moveTower(int n, char start, char finish, char tmp) {
if (n == 1) {
moveSingleDisk(start, finish);
}
else {
moveTower(n - 1, start, tmp, finish);
moveSingleDisk(start, finish);
moveTower(n - 1, tmp, finish, start);
}
}
二、子集求和问题
1.问题描述
给定一个整数集合和一个目标值,确定是否可以找到这个整数集合的一个子集,子集的和等于指定的目标值
其判定函数如下:
bool subsetSumExists(set<int>& set, int target);
2.递归策略及实现
选择一个元素,然后将其从集合中删除,创建一个更小的集合。
bool subsetSumExists(set<int>& ji_he, int target) {
if (ji_he.empty()) {
return target == 0;
}
else {
int element = *ji_he.begin();
ji_he.erase(element);
set<int> rest = ji_he;
return subsetSumExists(rest, target) || subsetSumExists(rest, target - element);
}
}
这个递归策略包含两个分支,一种包含特定的元素,另一种不包含该特定元素,可以称其为包含/排除模式,在涉及数组和字符串的应用中应注意识别。
三、字符排列
对于一个给定的字符集合可以产生其所有的排列组合。
实现函数如下:
set<string> generatePermutations(string str) {
set<string> result;
if (str == "") {
result.insert("");
}
else {
for (int i = 0; i < str.length(); i++) {
char ch = str[i];
string rest = str.substr(0, i) + str.substr(i + 1);
for (string s : generatePermutations(rest)) {
result.insert(ch + s);
}
}
}
return result;
}