当前位置:   article > 正文

体系班第十七节(经典递归)

体系班第十七节(经典递归)

1汉诺塔 

从左移到最右,圆盘必须满足小压大原则

写一个大方法,大方法包括两步:第一步将最后一个圆盘上面的所有的放到第二个塔上面,然后将最后一个圆盘放到最后塔上面,再把第二个塔上面圆盘全放在第三个塔上面

  1. #include <iostream>
  2. using namespace std;
  3. // 将 1~N 层圆盘从左 -> 右
  4. void leftToRight(int n);
  5. // 将 1~N 层圆盘从左 -> 中
  6. void leftToMid(int n);
  7. // 将 1~N 层圆盘从右 -> 中
  8. void rightToMid(int n);
  9. // 将 1~N 层圆盘从中 -> 右
  10. void midToRight(int n);
  11. // 将 1~N 层圆盘从中 -> 左
  12. void midToLeft(int n);
  13. // 将 1~N 层圆盘从右 -> 左
  14. void rightToLeft(int n);
  15. // 汉诺塔问题
  16. void hanoi1(int n) {
  17. leftToRight(n);
  18. }
  19. void leftToRight(int n) {
  20. if (n == 1) { // 基本情况
  21. cout << "Move 1 from left to right" << endl;
  22. return;
  23. }
  24. leftToMid(n - 1);
  25. cout << "Move " << n << " from left to right" << endl;
  26. midToRight(n - 1);
  27. }
  28. void leftToMid(int n) {
  29. if (n == 1) {
  30. cout << "Move 1 from left to mid" << endl;
  31. return;
  32. }
  33. leftToRight(n - 1);
  34. cout << "Move " << n << " from left to mid" << endl;
  35. rightToMid(n - 1);
  36. }
  37. void rightToMid(int n) {
  38. if (n == 1) {
  39. cout << "Move 1 from right to mid" << endl;
  40. return;
  41. }
  42. rightToLeft(n - 1);
  43. cout << "Move " << n << " from right to mid" << endl;
  44. leftToMid(n - 1);
  45. }
  46. void midToRight(int n) {
  47. if (n == 1) {
  48. cout << "Move 1 from mid to right" << endl;
  49. return;
  50. }
  51. midToLeft(n - 1);
  52. cout << "Move " << n << " from mid to right" << endl;
  53. leftToRight(n - 1);
  54. }
  55. void midToLeft(int n) {
  56. if (n == 1) {
  57. cout << "Move 1 from mid to left" << endl;
  58. return;
  59. }
  60. midToRight(n - 1);
  61. cout << "Move " << n << " from mid to left" << endl;
  62. rightToLeft(n - 1);
  63. }
  64. void rightToLeft(int n) {
  65. if (n == 1) {
  66. cout << "Move 1 from right to left" << endl;
  67. return;
  68. }
  69. rightToMid(n - 1);
  70. cout << "Move " << n << " from right to left" << endl;
  71. midToLeft(n - 1);
  72. }
  73. int main() {
  74. // 测试
  75. int n = 3; // 圆盘的层数
  76. hanoi1(n);
  77. return 0;
  78. }

 

递归2:把三个塔分为from other to 

  1. #include <iostream>
  2. using namespace std;
  3. // 汉诺塔问题
  4. void hanoi2(int n) {
  5. if (n > 0) {
  6. func(n, "left", "right", "mid");
  7. }
  8. }
  9. // 递归函数
  10. void func(int N, string from, string to, string other) {
  11. if (N == 1) { // 基本情况
  12. cout << "Move 1 from " << from << " to " << to << endl;
  13. } else {
  14. func(N - 1, from, other, to);
  15. cout << "Move " << N << " from " << from << " to " << to << endl;
  16. func(N - 1, other, to, from);
  17. }
  18. }
  19. int main() {
  20. // 测试
  21. int n = 3; // 圆盘的层数
  22. hanoi2(n);
  23. return 0;
  24. }

2打印一个字符串的全部子序列
递归思路:第一个参数是原字符串,第二个index是当前来到的字符,path是之前已经选好的部分串,第三个参数是所有结果的保存

  1. #include <vector>
  2. #include <string>
  3. using namespace std;
  4. class Solution {
  5. public:
  6. vector<string> subs(string s) {
  7. vector<char> str(s.begin(), s.end());
  8. string path = "";
  9. vector<string> ans;
  10. process1(str, 0, ans, path);
  11. return ans;
  12. }
  13. private:
  14. void process1(vector<char>& str, int index, vector<string>& ans, string path) {
  15. if (index == str.size()) {
  16. ans.push_back(path);
  17. return;
  18. }
  19. // 不要索引位置的字符
  20. process1(str, index + 1, ans, path);
  21. // 要索引位置的字符
  22. process1(str, index + 1, ans, path + str[index]);
  23. }
  24. };

 3题 求所有不同的子序列,只要改成set结构收集答案即可

4 打印一个字符串的全部排列

去除该字符后需要回溯去恢复现场

  1. #include <vector>
  2. #include <string>
  3. using namespace std;
  4. class Solution {
  5. public:
  6. vector<string> permutation1(string s) {
  7. vector<string> ans;
  8. if (s.empty()) {
  9. return ans;
  10. }
  11. string path = "";
  12. vector<char> rest(s.begin(), s.end());
  13. f(rest, path, ans);
  14. return ans;
  15. }
  16. private:
  17. void f(vector<char>& rest, string path, vector<string>& ans) {
  18. if (rest.empty()) {
  19. ans.push_back(path);
  20. } else {
  21. int N = rest.size();
  22. for (int i = 0; i < N; i++) {
  23. char cur = rest[i];
  24. rest.erase(rest.begin() + i);
  25. f(rest, path + cur, ans);
  26. rest.insert(rest.begin() + i, cur);
  27. }
  28. }
  29. }
  30. };

 递归2:

不停地做字符串前一位和后一位交换,而且是在原字符串上面交换

  1. #include <vector>
  2. #include <string>
  3. using namespace std;
  4. class Solution {
  5. public:
  6. vector<string> permutation2(string s) {
  7. vector<string> ans;
  8. if (s.empty()) {
  9. return ans;
  10. }
  11. char* str = &s[0];
  12. g1(str, 0, ans);
  13. return ans;
  14. }
  15. private:
  16. void g1(char* str, int index, vector<string>& ans) {
  17. if (str[index] == '\0') {
  18. ans.push_back(string(str));
  19. } else {
  20. for (int i = index; str[i] != '\0'; i++) {
  21. swap(str[index], str[i]);
  22. g1(str, index + 1, ans);
  23. swap(str[index], str[i]);
  24. }
  25. }
  26. }
  27. void swap(char& a, char& b) {
  28. char temp = a;
  29. a = b;
  30. b = temp;
  31. }
  32. };

5去重过后的排列

在上一题代码做改动,如果某个字符已经试过了,那就在后面在遇到时就不尝试了

 

  1. #include <vector>
  2. #include <string>
  3. using namespace std;
  4. class Solution {
  5. public:
  6. vector<string> permutation3(string s) {
  7. vector<string> ans;
  8. if (s.empty()) {
  9. return ans;
  10. }
  11. char* str = &s[0];
  12. g2(str, 0, ans);
  13. return ans;
  14. }
  15. private:
  16. void g2(char* str, int index, vector<string>& ans) {
  17. if (str[index] == '\0') {
  18. ans.push_back(string(str));
  19. } else {
  20. bool visited[256] = { false }; // 记录字符是否已被访问
  21. for (int i = index; str[i] != '\0'; i++) {
  22. if (!visited[str[i]]) { // 如果字符尚未访问过
  23. visited[str[i]] = true; // 标记字符已被访问
  24. swap(str[index], str[i]);
  25. g2(str, index + 1, ans);
  26. swap(str[index], str[i]);
  27. }
  28. }
  29. }
  30. }
  31. void swap(char& a, char& b) {
  32. char temp = a;
  33. a = b;
  34. b = temp;
  35. }
  36. };

 6 递归逆序栈

  1. #include<stack>
  2. using namespace std;
  3. //该函数的功能是返回栈底的元素
  4. int f(stack<int>& s)
  5. {
  6. int result = s.top();
  7. s.pop();
  8. if (s.empty())
  9. {
  10. return result;
  11. }
  12. else {
  13. int last = f(s);
  14. s.push(result);
  15. return last;
  16. }
  17. }
  18. void reverse(stack<int>& s)
  19. {
  20. if (s.empty())
  21. return;
  22. int i = f(s);
  23. reverse(s);
  24. s.push(i);
  25. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/256209
推荐阅读
相关标签
  

闽ICP备14008679号