汉诺塔问题的两种解法(递归和非递归)

196 阅读1分钟

1. LeetCode 面试题 08.06. 汉诺塔问题

解法一:递归

class Solution {
public:
    void hanota(vector<int>& A, vector<int>& B, vector<int>& C) {
        int n = A.size();
        move(n, A, B, C);
    }

    void move(int n, vector<int>& A, vector<int>& B, vector<int>& C)
    {
        if (n == 1)
        {
            C.push_back(A.back());
            A.pop_back();
            return;
        }

        move(n-1, A, C, B);
        C.push_back(A.back());
        A.pop_back();
        move(n-1, B, A, C);
    }
};

解法二:栈

class Solution {
    using A3 = array<vector<int>*, 3>;
public:
    void hanota(vector<int>& A, vector<int>& B, vector<int>& C) {
        int n = A.size();
        if (n == 0) return;
        stack<pair<int, A3>> st;
        st.push(make_pair(n, A3{&A, &B, &C}));
        while (!st.empty()){
            auto t = st.top();
            const auto& ps = t.second;
            st.pop();
            if (t.first == 1){
                ps[2]->push_back(ps[0]->back());
                ps[0]->pop_back();
            }else {
                // 用栈模仿函数递归调用的过程,要注意入栈的顺序恰好和函数调用顺序相反
                st.push(make_pair(t.first - 1, A3{ps[1], ps[0], ps[2]}));
                st.push(make_pair(1, A3{ps[0], ps[1], ps[2]}));
                st.push(make_pair(t.first - 1, A3{ps[0], ps[2], ps[1]}));
            }
        }
    }
};

要点const auto& ps = t.second;

这里要加const的原因:

const&表示array数组里的值不变,array数组里的值是指针,

指针值不变就是指针变量里存的内存地址不变,但是内存中的值可以改变

2. NC67 汉诺塔问题

解法一:递归

class Solution {
public:
    vector<string> getSolution(int n) {
        // write code here
        helper(n, "left", "mid", "right");
        return ans;
    }
private:
    vector<string> ans;

    void helper(int n, string left, string mid, string right)
    {
        if (n == 0) return;
        
        helper(n-1, left, right, mid);
        string s = "move from " + left + " to " + right;
        ans.push_back(s);
        helper(n-1, mid, left, right);
    }
};

解法二:栈

class Solution {
public:
    vector<string> getSolution(int n) {
        // write code here
        vector<string> res;
        stack<node> st;
        st.push({n, "left", "mid", "right"});    // 入栈
        while (!st.empty()){
            auto now = st.top();
            st.pop();
            n = now.n;
            string l = now.l;
            string m = now.m;
            string r = now.r;
            if (n == 1){
                res.push_back("move from "+l+" to "+r);
            }else{
                // 用栈模仿函数递归调用的过程,要注意入栈的顺序恰好和函数调用顺序相反
                st.push({n-1, m, l, r});
                st.push({1, l, m, r});
                st.push({n-1, l, r, m});
            }
        }
        return res;
    }
private:
    struct node{
        int n;
        string l;
        string m;
        string r;
    };
};