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

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);
}

相关推荐

  1. 算法体系-15 :贪心算法(下)

    2024-03-17 09:00:02       15 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-17 09:00:02       14 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-17 09:00:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-17 09:00:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-17 09:00:02       18 阅读

热门阅读

  1. Node.js 中的事件循环(Event Loop)

    2024-03-17 09:00:02       17 阅读
  2. MySQL模块---更新和删除数据

    2024-03-17 09:00:02       17 阅读
  3. FTP服务器的工作原理

    2024-03-17 09:00:02       14 阅读
  4. 序列化笔记

    2024-03-17 09:00:02       18 阅读
  5. 基于YOLO的自动驾驶目标检测研究综述

    2024-03-17 09:00:02       17 阅读
  6. 超实用绿色办公软件介绍

    2024-03-17 09:00:02       20 阅读
  7. 踏上机器学习的征程:探索基础概念与学习模式

    2024-03-17 09:00:02       20 阅读
  8. Golang的CSP模型讲解

    2024-03-17 09:00:02       20 阅读
  9. Android Framework开发之Linux +Vim命令

    2024-03-17 09:00:02       20 阅读
  10. Go 日期时间包装器:15条更便捷的时间处理

    2024-03-17 09:00:02       18 阅读