赞
踩
1汉诺塔
从左移到最右,圆盘必须满足小压大原则
写一个大方法,大方法包括两步:第一步将最后一个圆盘上面的所有的放到第二个塔上面,然后将最后一个圆盘放到最后塔上面,再把第二个塔上面圆盘全放在第三个塔上面
- #include <iostream>
-
- using namespace std;
-
- // 将 1~N 层圆盘从左 -> 右
- void leftToRight(int n);
-
- // 将 1~N 层圆盘从左 -> 中
- void leftToMid(int n);
-
- // 将 1~N 层圆盘从右 -> 中
- void rightToMid(int n);
-
- // 将 1~N 层圆盘从中 -> 右
- void midToRight(int n);
-
- // 将 1~N 层圆盘从中 -> 左
- void midToLeft(int n);
-
- // 将 1~N 层圆盘从右 -> 左
- void rightToLeft(int n);
-
- // 汉诺塔问题
- void hanoi1(int n) {
- leftToRight(n);
- }
-
- void leftToRight(int n) {
- if (n == 1) { // 基本情况
- cout << "Move 1 from left to right" << endl;
- return;
- }
- leftToMid(n - 1);
- cout << "Move " << n << " from left to right" << endl;
- midToRight(n - 1);
- }
-
- void leftToMid(int n) {
- if (n == 1) {
- cout << "Move 1 from left to mid" << endl;
- return;
- }
- leftToRight(n - 1);
- cout << "Move " << n << " from left to mid" << endl;
- rightToMid(n - 1);
- }
-
- void rightToMid(int n) {
- if (n == 1) {
- cout << "Move 1 from right to mid" << endl;
- return;
- }
- rightToLeft(n - 1);
- cout << "Move " << n << " from right to mid" << endl;
- leftToMid(n - 1);
- }
-
- void midToRight(int n) {
- if (n == 1) {
- cout << "Move 1 from mid to right" << endl;
- return;
- }
- midToLeft(n - 1);
- cout << "Move " << n << " from mid to right" << endl;
- leftToRight(n - 1);
- }
-
- void midToLeft(int n) {
- if (n == 1) {
- cout << "Move 1 from mid to left" << endl;
- return;
- }
- midToRight(n - 1);
- cout << "Move " << n << " from mid to left" << endl;
- rightToLeft(n - 1);
- }
-
- void rightToLeft(int n) {
- if (n == 1) {
- cout << "Move 1 from right to left" << endl;
- return;
- }
- rightToMid(n - 1);
- cout << "Move " << n << " from right to left" << endl;
- midToLeft(n - 1);
- }
-
- int main() {
- // 测试
- int n = 3; // 圆盘的层数
- hanoi1(n);
- return 0;
- }

递归2:把三个塔分为from other to
- #include <iostream>
-
- using namespace std;
-
- // 汉诺塔问题
- void hanoi2(int n) {
- if (n > 0) {
- func(n, "left", "right", "mid");
- }
- }
-
- // 递归函数
- void func(int N, string from, string to, string other) {
- if (N == 1) { // 基本情况
- cout << "Move 1 from " << from << " to " << to << endl;
- } else {
- func(N - 1, from, other, to);
- cout << "Move " << N << " from " << from << " to " << to << endl;
- func(N - 1, other, to, from);
- }
- }
-
- int main() {
- // 测试
- int n = 3; // 圆盘的层数
- hanoi2(n);
- return 0;
- }

2打印一个字符串的全部子序列
递归思路:第一个参数是原字符串,第二个index是当前来到的字符,path是之前已经选好的部分串,第三个参数是所有结果的保存
- #include <vector>
- #include <string>
-
- using namespace std;
-
- class Solution {
- public:
- vector<string> subs(string s) {
- vector<char> str(s.begin(), s.end());
- string path = "";
- vector<string> ans;
- process1(str, 0, ans, path);
- return ans;
- }
-
- private:
- void process1(vector<char>& str, int index, vector<string>& ans, string path) {
- if (index == str.size()) {
- ans.push_back(path);
- return;
- }
- // 不要索引位置的字符
- process1(str, index + 1, ans, path);
- // 要索引位置的字符
- process1(str, index + 1, ans, path + str[index]);
- }
- };

3题 求所有不同的子序列,只要改成set结构收集答案即可
4 打印一个字符串的全部排列
去除该字符后需要回溯去恢复现场
- #include <vector>
- #include <string>
-
- using namespace std;
-
- class Solution {
- public:
- vector<string> permutation1(string s) {
- vector<string> ans;
- if (s.empty()) {
- return ans;
- }
- string path = "";
- vector<char> rest(s.begin(), s.end());
- f(rest, path, ans);
- return ans;
- }
-
- private:
- void f(vector<char>& rest, string path, vector<string>& ans) {
- if (rest.empty()) {
- ans.push_back(path);
- } else {
- int N = rest.size();
- for (int i = 0; i < N; i++) {
- char cur = rest[i];
- rest.erase(rest.begin() + i);
- f(rest, path + cur, ans);
- rest.insert(rest.begin() + i, cur);
- }
- }
- }
- };

递归2:
不停地做字符串前一位和后一位交换,而且是在原字符串上面交换
- #include <vector>
- #include <string>
-
- using namespace std;
-
- class Solution {
- public:
- vector<string> permutation2(string s) {
- vector<string> ans;
- if (s.empty()) {
- return ans;
- }
- char* str = &s[0];
- g1(str, 0, ans);
- return ans;
- }
-
- private:
- void g1(char* str, int index, vector<string>& ans) {
- if (str[index] == '\0') {
- ans.push_back(string(str));
- } else {
- for (int i = index; str[i] != '\0'; i++) {
- swap(str[index], str[i]);
- g1(str, index + 1, ans);
- swap(str[index], str[i]);
- }
- }
- }
-
- void swap(char& a, char& b) {
- char temp = a;
- a = b;
- b = temp;
- }
- };

5去重过后的排列
在上一题代码做改动,如果某个字符已经试过了,那就在后面在遇到时就不尝试了
- #include <vector>
- #include <string>
-
- using namespace std;
-
- class Solution {
- public:
- vector<string> permutation3(string s) {
- vector<string> ans;
- if (s.empty()) {
- return ans;
- }
- char* str = &s[0];
- g2(str, 0, ans);
- return ans;
- }
-
- private:
- void g2(char* str, int index, vector<string>& ans) {
- if (str[index] == '\0') {
- ans.push_back(string(str));
- } else {
- bool visited[256] = { false }; // 记录字符是否已被访问
- for (int i = index; str[i] != '\0'; i++) {
- if (!visited[str[i]]) { // 如果字符尚未访问过
- visited[str[i]] = true; // 标记字符已被访问
- swap(str[index], str[i]);
- g2(str, index + 1, ans);
- swap(str[index], str[i]);
- }
- }
- }
- }
-
- void swap(char& a, char& b) {
- char temp = a;
- a = b;
- b = temp;
- }
- };

6 递归逆序栈
- #include<stack>
- using namespace std;
- //该函数的功能是返回栈底的元素
- int f(stack<int>& s)
- {
- int result = s.top();
- s.pop();
- if (s.empty())
- {
- return result;
- }
- else {
- int last = f(s);
- s.push(result);
- return last;
- }
- }
- void reverse(stack<int>& s)
- {
- if (s.empty())
- return;
- int i = f(s);
- reverse(s);
- s.push(i);
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。