国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【leetcode刷題之路】劍指Offer(3)——搜索與回溯算法

這篇具有很好參考價(jià)值的文章主要介紹了【leetcode刷題之路】劍指Offer(3)——搜索與回溯算法。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

7 搜索與回溯算法

7.1 【BFS】劍指 Offer 32 - I - 從上到下打印二叉樹

https://leetcode.cn/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof/

??這里借助隊(duì)列來實(shí)現(xiàn)廣度優(yōu)先遍歷,由于需要訪問每一層的節(jié)點(diǎn),而且這一層訪問才可以訪問下一層,所以可以考慮隊(duì)列的先進(jìn)先出,先把每一層的節(jié)點(diǎn)加入隊(duì)列,然后把這一層的節(jié)點(diǎn)訪問的同時(shí),也把它們的左右子樹加入隊(duì)列,這樣每一層訪問完之后緊接著就是下一層的節(jié)點(diǎn)。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> levelOrder(TreeNode* root) {
        vector<int> ans;
        queue<TreeNode*> q;
        if(root!=nullptr) q.push(root);
        while(!q.empty())
        {
            int n = q.size();
            for(int i=0;i<n;i++)
            {
                TreeNode *tmp = q.front();
                q.pop();
                ans.push_back(tmp->val);
                if(tmp->left!=nullptr) q.push(tmp->left);
                if(tmp->right!=nullptr) q.push(tmp->right); 
            }
        }
        return ans;
    }
};
7.2【BFS】劍指 Offer 32 - II - 從上到下打印二叉樹 II

https://leetcode.cn/problems/cong-shang-dao-xia-da-yin-er-cha-shu-ii-lcof/

??這里借助隊(duì)列來實(shí)現(xiàn)廣度優(yōu)先遍歷,由于需要訪問每一層的節(jié)點(diǎn),而且這一層訪問才可以訪問下一層,所以可以考慮隊(duì)列的先進(jìn)先出,先把每一層的節(jié)點(diǎn)加入隊(duì)列,然后把這一層的節(jié)點(diǎn)訪問的同時(shí),也把它們的左右子樹加入隊(duì)列,這樣每一層訪問完之后緊接著就是下一層的節(jié)點(diǎn)。以上一題不同的是每層的數(shù)要存放為一個(gè)向量,最后返回多個(gè)向量。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> ans;
        queue<TreeNode*> q;
        if(root!=nullptr) q.push(root);
        while(!q.empty())
        {
            int n = q.size();
            vector<int> tmp;
            for(int i=0;i<n;i++)
            {
                TreeNode *node = q.front();
                q.pop();
                tmp.push_back(node->val);
                if(node->left!=nullptr) q.push(node->left);
                if(node->right!=nullptr) q.push(node->right); 
            }
            ans.push_back(tmp);
        }
        return ans;
    }
};
7.3 【BFS】【雙端隊(duì)列】劍指 Offer 32 - III - 從上到下打印二叉樹 III

https://leetcode.cn/problems/cong-shang-dao-xia-da-yin-er-cha-shu-iii-lcof/

??這里借助雙端隊(duì)列來實(shí)現(xiàn)廣度優(yōu)先遍歷,由于需要訪問每一層的節(jié)點(diǎn),而且這一層訪問才可以訪問下一層,對(duì)于奇數(shù)層來說,訪問的順序是從左到右,而偶數(shù)層是從右到左,所以可以做如下操作:

  • 奇數(shù)層:從左往右取隊(duì)列元素,但是每個(gè)元素先取其左子樹再取右子樹,然后從隊(duì)列末尾插入;
  • 偶數(shù)層:從右往左取隊(duì)列元素,但是每個(gè)元素先取其右子樹再取左子樹,然后從隊(duì)列頭部插入。

??這樣就可以保證每一層的順序連在一起時(shí)之字形順序了。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> ans;
        deque<TreeNode*> q;
        if(root!=nullptr) q.push_back(root);
        bool flag = true;
        while(!q.empty())
        {
            int n = q.size();
            vector<int> tmp;
            for(int i=0;i<n;i++)
            {
                TreeNode *node;
                if(flag)
                {
                    node = q.front();
                    q.pop_front();
                    if(node->left!=nullptr) q.push_back(node->left);
                    if(node->right!=nullptr) q.push_back(node->right);
                }
                else
                {
                    node = q.back();
                    q.pop_back();
                    if(node->right!=nullptr) q.push_front(node->right);
                    if(node->left!=nullptr) q.push_front(node->left);
                }
                tmp.push_back(node->val);
            }
            flag = !flag;
            ans.push_back(tmp);
        }
        return ans;
    }
};
7.4 【BFS】劍指 Offer 26 - 樹的子結(jié)構(gòu)

https://leetcode.cn/problems/shu-de-zi-jie-gou-lcof/

??這里把A的每個(gè)結(jié)點(diǎn)與B進(jìn)行比較,如果結(jié)點(diǎn)相同則看它們的左右子樹是否相同即可,這里借助自定義函數(shù)來判斷A和B是否為包含關(guān)系,也就是A包含B,函數(shù)定義如下:

  • 如果B為空,說明此時(shí)B的所有結(jié)點(diǎn)遍歷完了,B為A的子樹;
  • 如果B不為空A為空,說明此時(shí)A的所有結(jié)點(diǎn)遍歷完了但是B還有結(jié)點(diǎn),則B不是A的子樹;
  • 如果此時(shí)A和B的結(jié)點(diǎn)相同,還要判斷它們的左右子樹是否相同。
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool is_contain(TreeNode* A, TreeNode* B) {
        if(B==nullptr) return true;
        if(A==nullptr) return false;

        if(A->val==B->val) return is_contain(A->left,B->left) && is_contain(A->right,B->right);
        else return false;
    }

    bool isSubStructure(TreeNode* A, TreeNode* B) {
        if(A==nullptr || B==nullptr) return false;

        if(A->val==B->val && is_contain(A,B)) return true;
        else return isSubStructure(A->left,B) || isSubStructure(A->right,B);
    }
};
7.5 【遞歸】劍指 Offer 27 - 二叉樹的鏡像

https://leetcode.cn/problems/er-cha-shu-de-jing-xiang-lcof/

??直接交換每個(gè)結(jié)點(diǎn)的左右子樹,然后遞歸返回即可。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* mirrorTree(TreeNode* root) {
        if(root==nullptr) return nullptr;
        swap(root->left,root->right);
        mirrorTree(root->left);
        mirrorTree(root->right);
        return root;
    }
};
7.6 【遞歸】【雙指針】劍指 Offer 28 - 對(duì)稱的二叉樹

https://leetcode.cn/problems/dui-cheng-de-er-cha-shu-lcof/

??利用雙指針分別從樹的左右子樹往下判斷是否對(duì)稱,這里需要注意的是雙指針最后必須同時(shí)為空才行,如果有一個(gè)先為空說明這棵二叉樹是不對(duì)稱的,同時(shí)雙指針也要對(duì)稱著向下移動(dòng),比如l左移r右移、l右移r左移。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool check(TreeNode* l, TreeNode* r) {
        if(l==nullptr && r==nullptr) return true;
        if(l==nullptr || r==nullptr) return false;
        return l->val==r->val && check(l->left,r->right) && check(l->right,r->left);
    }

    bool isSymmetric(TreeNode* root) {
        return check(root,root);
    }
};
7.7 【DFS】【回溯】【剪枝】劍指 Offer 12 - 矩陣中的路徑

https://leetcode.cn/problems/ju-zhen-zhong-de-lu-jing-lcof/

??這里我們首先找到矩陣中和字符串的第一個(gè)字符對(duì)應(yīng)的位置,然后從這個(gè)位置開始分別向上下左右深度搜索,直到找到與字符串完成對(duì)應(yīng)的一條搜索路徑即可,但是這里需要設(shè)置一些剪枝規(guī)則提前終止不必要的搜索:

  • 如果訪問越界了,需要提前終止搜索;
  • 如果當(dāng)前在矩陣中訪問到的字符與目前在字符串中遍歷到的字符不一樣,需要提前終止搜索。

??這里為了防止矩陣中的元素被重復(fù)使用,訪問過的元素統(tǒng)一賦值為空,當(dāng)這一輪搜索結(jié)束之后再用字符串賦值回去,避免影響判斷。

class Solution {
private:
    int row,col;
public:
    bool exist(vector<vector<char>>& board, string word) {
        row = board.size();
        col = board[0].size();
        for(int i=0;i<row;i++)
        {
            for(int j=0;j<col;j++)
            {
                if(dfs(board,word,i,j,0)) return true;
            }
        }
        return false;
    }

    bool dfs(vector<vector<char>>& board, string word, int i, int j, int k) {
        //矩陣訪問越界and當(dāng)前訪問字符不一致時(shí),需要提前終止搜索,返回false
        if(i>=row || i<0 || j>=col || j<0 || board[i][j]!=word[k]) return false;
        //字符串遍歷到最后一個(gè)字符,說明找到了一條路徑,返回true
        if(k==word.size()-1) return true;
        //避免矩陣重復(fù)訪問,已訪問的賦值為空
        board[i][j] = ' ';
        //上下左右深度搜索
        bool flag = dfs(board,word,i-1,j,k+1) || dfs(board,word,i+1,j,k+1) || 
                    dfs(board,word,i,j-1,k+1) || dfs(board,word,i,j+1,k+1);
        //此輪搜索結(jié)束,已訪問過的再賦值回去
        board[i][j] = word[k];
        return flag;
    }
};
7.8 【DFS】劍指 Offer 13 - 機(jī)器人的運(yùn)動(dòng)范圍

https://leetcode.cn/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/

??利用DFS解題,雖然機(jī)器人可以上下左右移動(dòng),但是最后算的是機(jī)器人可以到達(dá)多少個(gè)格子,所以可以把上下左右簡(jiǎn)化為下和右兩個(gè)行動(dòng),并且設(shè)置一個(gè)數(shù)組visit來記錄每個(gè)格子是否被訪問過。這道題的難點(diǎn)在于行坐標(biāo)和列坐標(biāo)的位數(shù)之和如何快速計(jì)算,這里我們可以發(fā)現(xiàn)一個(gè)規(guī)律,假設(shè)坐標(biāo)為18,19,20,21,22時(shí),數(shù)位和分別為9,10,2,3,4,這里如果坐標(biāo)不是10的倍數(shù),那么數(shù)位和隨著坐標(biāo)數(shù)的增加依次加1,而當(dāng)來到20時(shí),數(shù)位和直接變成了2,比19的數(shù)位和少8,同理坐標(biāo)29,30,31的數(shù)位和分別是11,3,4,所以可以總結(jié)出這樣的規(guī)律:

  • 如果坐標(biāo)不是10的倍數(shù),數(shù)位和較之前的坐標(biāo)加1;
  • 如果坐標(biāo)是10的倍數(shù)。數(shù)位和較之前的坐標(biāo)減8.
class Solution {
public:
    int movingCount(int m, int n, int k) {
        vector<vector<bool>> visit(m,vector<bool>(n,false));
        return dfs(0,0,0,0,visit,m,n,k);
    }

    int dfs(int i, int j, int si, int sj, vector<vector<bool>> &visit, int m, int n, int k) {
        if(i<0 || i>=m || j<0 || j>=n || si+sj>k || visit[i][j]) return 0;
        visit[i][j] = true;
        int new_si = (i+1)%10 != 0 ? si+1 : si-8;
        int new_sj = (j+1)%10 != 0 ? sj+1 : sj-8;
        return 1 + dfs(i,j+1,si,new_sj,visit,m,n,k) + dfs(i+1,j,new_si,sj,visit,m,n,k);
    }
};
7.9 【DFS】【遞歸】劍指 Offer 34 - 二叉樹中和為某一值的路徑

https://leetcode.cn/problems/er-cha-shu-zhong-he-wei-mou-yi-zhi-de-lu-jing-lcof/

??利用DFS解題,順著根結(jié)點(diǎn)先往一個(gè)子結(jié)點(diǎn)方向遍歷,然后再去遍歷另一個(gè),這里的難點(diǎn)在于精準(zhǔn)判斷是否達(dá)到目標(biāo)和,一共需要以下幾個(gè)條件:

  • 截止目前的路徑上的val之和等于target;
  • 目前結(jié)點(diǎn)是葉子結(jié)點(diǎn),也就是該結(jié)點(diǎn)的左右結(jié)點(diǎn)都為空。
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> ans;
    vector<vector<int>> pathSum(TreeNode* root, int target) {
        vector<int> path;
        dfs(root,target,path);
        return ans;
    }

    void dfs(TreeNode* root, int target, vector<int> path) {
        if(root==nullptr) return;
        path.push_back(root->val);
        if(root->val==target && root->left==nullptr && root->right==nullptr)
        {
            ans.push_back(path);
            return;
        }
        dfs(root->left,target-root->val,path);
        dfs(root->right,target-root->val,path);
    }
};
7.10 【DFS】【遞歸】【雙指針】劍指 Offer 36 - 二叉搜索樹與雙向鏈表

https://leetcode.cn/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/

??這道題其實(shí)就是把給出的這個(gè)二叉樹變成中序遍歷的結(jié)果輸出,然后在中序遍歷的過程中改變左右子樹的指向即可,使之變成雙向循環(huán)鏈表,這里借助雙指針來構(gòu)造循環(huán)鏈表,head指向循環(huán)鏈表的開始,pre指向中序遍歷過程中訪問到的每個(gè)結(jié)點(diǎn)的前序結(jié)點(diǎn),按照中序遍歷的過程進(jìn)行DFS,遍歷到最下面的左子樹時(shí),開始構(gòu)造鏈表,此時(shí)左子樹應(yīng)該是當(dāng)前root的前驅(qū),這樣就構(gòu)造出了一個(gè)循環(huán),然后依次往上返回構(gòu)造其他循環(huán),最后要把頭尾連接起來。

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;

    Node() {}

    Node(int _val) {
        val = _val;
        left = NULL;
        right = NULL;
    }

    Node(int _val, Node* _left, Node* _right) {
        val = _val;
        left = _left;
        right = _right;
    }
};
*/
class Solution {
public:
    Node *head=nullptr, *pre=nullptr;

    Node* treeToDoublyList(Node* root) {
        if(root==nullptr) return root;
        dfs(root);
        head->left = pre;
        pre->right = head;
        return head;
    }

    void dfs(Node* root) {
        if(root==nullptr) return;
        dfs(root->left);
        if(pre!=nullptr) pre->right = root;
        else head = root;
        root->left = pre;
        pre = root;
        dfs(root->right);
    }
};
7.11 【DFS】劍指 Offer 54 - 二叉搜索樹的第k大節(jié)點(diǎn)

https://leetcode.cn/problems/er-cha-sou-suo-shu-de-di-kda-jie-dian-lcof/

??這道題是找第k大的結(jié)點(diǎn),二叉搜索樹的中序遍歷結(jié)果是從小到大排序,所以其實(shí)就是對(duì)二叉搜索樹進(jìn)行倒過來的中序遍歷,每遍歷一個(gè)元素k–,當(dāng)k為0時(shí)就是最終結(jié)果。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int ans = 0;
    int kthLargest(TreeNode* root, int k) {
        dfs(root,k);
        return ans;
    }

    void dfs(TreeNode* root,int &k) {
        if(root==nullptr) return;
        dfs(root->right,k);
        k--;
        if(k==0) ans = root->val;
        dfs(root->left,k);
    }
};
7.12 【DFS】劍指 Offer 55 - I - 二叉樹的深度

https://leetcode.cn/problems/er-cha-shu-de-shen-du-lcof/

??考察深度優(yōu)先遍歷,從上往下深度搜索,沒找到一個(gè)節(jié)點(diǎn)就把當(dāng)前的深度dpt加1,最后取最大的那個(gè)dpt即可。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int depth = 1;
    int maxDepth(TreeNode* root) {
        if(root==nullptr) return 0;
        dfs(root,0);
        return depth;
    }
    
    void dfs(TreeNode* root, int dpt) {
        if(root==nullptr)
        {
            depth = max(depth,dpt);
            return;
        }
        dpt++;
        dfs(root->left,dpt);
        dfs(root->right,dpt);
    }
};
7.13 【DFS】劍指 Offer 55 - II - 平衡二叉樹

https://leetcode.cn/problems/ping-heng-er-cha-shu-lcof/

??采用自底向上的方法,首先判斷最下面的節(jié)點(diǎn)是否滿足平衡二叉樹的條件,不滿足就把當(dāng)前高度賦值為-1,這樣一步步從下往上遞增,最后只需看根結(jié)點(diǎn)的高度是多少即可,如果采用自頂向下的話則會(huì)存在某些節(jié)點(diǎn)多次計(jì)算高度,會(huì)增加時(shí)間復(fù)雜度。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isBalanced(TreeNode* root) {
        if(depth(root)!=-1) return true;
        else return false;
    }

    int depth(TreeNode* root) {
        if(root==nullptr) return 0;
        int left_depth = depth(root->left);
        int right_depth = depth(root->right);
        if(left_depth == -1 || right_depth == -1 || abs(left_depth - right_depth) > 1)
        {
            return -1;
        }
        else return max(left_depth,right_depth) + 1;
    }
};
7.14 【位運(yùn)算】劍指 Offer 64 - 求1+2+…+n

https://leetcode.cn/problems/qiu-12n-lcof/

??求和公式為sum=n*(n+1)/2,這里為什么用bool呢,其實(shí)用char也行,因?yàn)樗鼈兌颊加靡粋€(gè)字節(jié),意思就是構(gòu)造了一個(gè)n*(n+1)的數(shù)組,然后先計(jì)算這個(gè)數(shù)組一共多少字節(jié),對(duì)于除2操作直接位運(yùn)算就行了。

class Solution {
public:
    int sumNums(int n) {
        bool ans[n][n+1];
        return sizeof(ans)>>1;
    }
};
7.15 【DFS】【遞歸】劍指 Offer 68 - I - 二叉搜索樹的最近公共祖先

https://leetcode.cn/problems/er-cha-sou-suo-shu-de-zui-jin-gong-gong-zu-xian-lcof/

??這道題需要明白一點(diǎn),就是x的值一定是在p和q之間的,所以在深度遍歷時(shí)只需比較當(dāng)前根節(jié)點(diǎn)的值和p、q的值的大小即可,如果當(dāng)前節(jié)點(diǎn)的值比p和q都大,說明最近公共祖先在左子樹,如果當(dāng)前節(jié)點(diǎn)的值比p和q都小,說明最近公共祖先在右子樹,如果都不滿足說明目前找到的就是最近公共祖先了。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
       if(root->val > p->val && root->val > q->val)
        {
            return lowestCommonAncestor(root->left,p,q);
        }
        else if(root->val < p->val && root->val < q->val)
        {
            return lowestCommonAncestor(root->right,p,q);
        }
        else return root;
    }
};
7.16 【DFS】劍指 Offer 68 - II - 二叉樹的最近公共祖先

https://leetcode.cn/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof/

??這題為一般二叉樹中找最近公共祖先,首先要明確公共祖先的判斷標(biāo)準(zhǔn),共有以下三點(diǎn):

  • (1)p和q在二叉樹兩側(cè)(也就是一個(gè)在左子樹一個(gè)在右子樹),則找最近的root結(jié)點(diǎn);
  • (2)p和q在二叉樹同側(cè)(也就是同在左子樹或者右子樹),則找p或者q;

??下面定義雙指針left和right來判斷目前節(jié)點(diǎn)的左右子樹中是否有p和q,并給出以下判斷標(biāo)準(zhǔn):

  • (1)如果left和right均不為空,說明p和q一個(gè)在左子樹一個(gè)在右子樹,返回當(dāng)前root節(jié)點(diǎn);
  • (2)如果left為空,right不為空,說明p和q都在右子樹中,返回right;
  • (3)如果left不為空,right為空,說明p和q都在左子樹中,返回left。
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root==nullptr || root==p || root==q) return root;
        TreeNode* left = lowestCommonAncestor(root->left,p,q);
        TreeNode* right = lowestCommonAncestor(root->right,p,q);
        if(left==nullptr) return right;
        if(right==nullptr) return left;
        return root;
    }
};
7.17 【DFS】【模擬】劍指 Offer 37 - 序列化二叉樹

https://leetcode.cn/problems/xu-lie-hua-er-cha-shu-lcof/

??本題主要實(shí)現(xiàn)兩個(gè)功能,分別是二叉樹的序列化和反序列化,也就是給定字符串變成二叉樹,或者給定二叉樹變成字符串,下面分開來介紹實(shí)現(xiàn)思路:
(1)二叉樹->字符串
??這個(gè)其實(shí)就是對(duì)二叉樹進(jìn)行中序遍歷即可,然后把每個(gè)節(jié)點(diǎn)的值保存到字符串中,難點(diǎn)在于如何把整數(shù)轉(zhuǎn)變成字符串,因?yàn)檫@里的數(shù)值可能是多位數(shù)或者負(fù)數(shù),所以這里定義了一個(gè)函數(shù)int_to_str()來實(shí)現(xiàn)將整數(shù)轉(zhuǎn)變?yōu)樽址?,同時(shí)在函數(shù)tree_to_str()中實(shí)現(xiàn)將二叉樹轉(zhuǎn)為字符串,這里注意每個(gè)數(shù)值后面要加上逗號(hào)’,‘。
(2)字符串->二叉樹
??這個(gè)就比較難了,首先要把字符串中的字符轉(zhuǎn)為數(shù)字,這里通過自定義函數(shù)str_to_int()來實(shí)現(xiàn),接下來就是為每一個(gè)生成的數(shù)值構(gòu)造一個(gè)節(jié)點(diǎn),按照中序遍歷的情況依次構(gòu)造二叉樹,當(dāng)上述準(zhǔn)備工作完成之后,下面就是要對(duì)給定的字符串進(jìn)行切割,分割標(biāo)準(zhǔn)為逗號(hào)’,',遍歷是每遇到逗號(hào)說明是一個(gè)節(jié)點(diǎn),然后把這個(gè)節(jié)點(diǎn)通過上述兩步操作插入到二叉樹中即可。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Codec {
private:
        string int_to_str(int num) {
        bool flag = true;
        string ans;
        if(num < 0)
        {
            num = -num;
            flag = false;
        }
        while(num)
        {
            ans.insert(ans.begin(), num % 10 + '0');
            num /= 10;
        }
        if(flag==false) ans.insert(ans.begin(),'-');
        return ans;
    }

    int str_to_int(string s) {
        int idx = 0;
        bool flag = true;
        int ans = 0;
        if(s[idx]=='-')
        {
            flag = false;
            idx++;
        }
        while(idx < s.size())
        {
            ans = s[idx] - '0' + ans * 10;
            idx++;
        }
        if(flag==false) ans = -ans;
        return ans;
    }

    void tree_to_str(TreeNode* root, string& str) {
        if(root==nullptr)
        {
            str += "/,";
            return;
        }
        str += int_to_str(root->val);
        str += ",";
        tree_to_str(root->left, str);
        tree_to_str(root->right, str);
    }

    TreeNode* str_to_tree(vector<string>& s, int& idx) {
        if(s[idx]=="/") return nullptr;
        int val = str_to_int(s[idx]);
        TreeNode* root = new TreeNode(val);
        root->left = str_to_tree(s, ++idx);
        root->right = str_to_tree(s, ++idx);
        return root;
    }

public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        string ans;
        tree_to_str(root,ans);
        return ans;
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        vector<string> s;
        int idx = 0;
        while(idx < data.size())
        {
            int tmp = idx;
            while(data[idx]!=',') idx++;
            string now = data.substr(tmp, idx - tmp);
            s.push_back(now);
            idx++;
        }
        idx = 0;
        TreeNode* root = str_to_tree(s, idx);
        return root;
    }
};

// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));
7.18 【DFS】【回溯】【模擬】劍指 Offer 38 - 字符串的排列

https://leetcode.cn/problems/zi-fu-chuan-de-pai-lie-lcof/

??這題難點(diǎn)在于如何保證字符不重復(fù)遍歷,同時(shí)也要保證最后得到的字符串里面沒有重復(fù)的字符串,這里考慮到可能原始的字符串里會(huì)有一些重復(fù)字符,所以先對(duì)原始的字符串進(jìn)行排序,然后定義一個(gè)數(shù)組visited來保存每一位是否被訪問過,而在深度遍歷的時(shí)候,對(duì)于每次訪問的字符,也要判斷它是否為重復(fù)的字符,防止重復(fù)的字符被多次訪問,但最后其實(shí)都是得到的同一個(gè)字符串,最后本次遍歷完之后還要把臨時(shí)字符串tmp和visited置回原來的狀態(tài)。文章來源地址http://www.zghlxwxcb.cn/news/detail-547195.html

class Solution {
public:
    vector<string> ans;
    vector<int> visited;

    void dfs(string &s, int i, int length, string &tmp) {
        if(i==length)
        {
            ans.push_back(tmp);
            return;
        }

        for(int j=0;j<length;j++)
        {
            if(visited[j] || (j>0 && !visited[j-1] && s[j-1]==s[j])) continue;

            visited[j] = 1;
            tmp.push_back(s[j]);

            dfs(s,i+1,length,tmp);
            tmp.pop_back();
            visited[j] = 0;
        }
    }

    vector<string> permutation(string s) {
        int length = s.size();
        visited.resize(length);
        string tmp;

        sort(s.begin(),s.end());
        dfs(s,0,length,tmp);

        return ans;
    }
};

到了這里,關(guān)于【leetcode刷題之路】劍指Offer(3)——搜索與回溯算法的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 劍指 Offer ??!13. 機(jī)器人的運(yùn)動(dòng)范圍(回溯算法)

    劍指 Offer 13. 機(jī)器人的運(yùn)動(dòng)范圍 地上有一個(gè)m行n列的方格,從坐標(biāo) [0,0] 到坐標(biāo) [m-1,n-1] 。一個(gè)機(jī)器人從坐標(biāo) [0, 0] 的格子開始移動(dòng),它每次可以向左、右、上、下移動(dòng)一格(不能移動(dòng)到方格外),也不能進(jìn)入行坐標(biāo)和列坐標(biāo)的數(shù)位之和大于k的格子。例如,當(dāng)k為18時(shí),機(jī)器人能

    2024年02月11日
    瀏覽(19)
  • 劍指offer(C++)-JZ12:矩陣中的路徑(算法-回溯)

    劍指offer(C++)-JZ12:矩陣中的路徑(算法-回溯)

    作者:翟天保Steven 版權(quán)聲明:著作權(quán)歸作者所有,商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處 題目描述: 請(qǐng)?jiān)O(shè)計(jì)一個(gè)函數(shù),用來判斷在一個(gè)n乘m的矩陣中是否存在一條包含某長(zhǎng)度為len的字符串所有字符的路徑。路徑可以從矩陣中的任意一個(gè)格子開始,每一步可以

    2024年02月11日
    瀏覽(23)
  • 劍指offer(C++)-JZ13:機(jī)器人的運(yùn)動(dòng)范圍(算法-回溯)

    劍指offer(C++)-JZ13:機(jī)器人的運(yùn)動(dòng)范圍(算法-回溯)

    作者:翟天保Steven 版權(quán)聲明:著作權(quán)歸作者所有,商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處 題目描述: 地上有一個(gè) rows 行和 cols 列的方格。坐標(biāo)從 [0,0] 到 [rows-1,cols-1] 。一個(gè)機(jī)器人從坐標(biāo) [0,0] 的格子開始移動(dòng),每一次只能向左,右,上,下四個(gè)方向移動(dòng)一格,

    2024年02月12日
    瀏覽(37)
  • 劍指 Offer 12. 矩陣中的路徑 / LeetCode 79. 單詞搜索(深度優(yōu)先搜索)

    劍指 Offer 12. 矩陣中的路徑 / LeetCode 79. 單詞搜索(深度優(yōu)先搜索)

    鏈接:劍指 Offer 12. 矩陣中的路徑;LeetCode 79. 單詞搜索 難度:中等 給定一個(gè) m x n 二維字符網(wǎng)格 board 和一個(gè)字符串單詞 word 。如果 word 存在于網(wǎng)格中,返回 true ;否則,返回 false 。 單詞必須按照字母順序,通過相鄰的單元格內(nèi)的字母構(gòu)成,其中“相鄰”單元格是那些水平相

    2024年02月02日
    瀏覽(29)
  • (搜索) 劍指 Offer 12. 矩陣中的路徑 ——【Leetcode每日一題】

    (搜索) 劍指 Offer 12. 矩陣中的路徑 ——【Leetcode每日一題】

    難度:中等 給定一個(gè) m * n 二維字符網(wǎng)格 board 和一個(gè)字符串單詞 word 。如果 word 存在于網(wǎng)格中,返回 true ;否則,返回 false 。 單詞必須按照字母順序,通過相鄰的單元格內(nèi)的字母構(gòu)成,其中“相鄰”單元格是那些水平相鄰或垂直相鄰的單元格。同一個(gè)單元格內(nèi)的字母不允許

    2024年02月12日
    瀏覽(28)
  • (搜索) 劍指 Offer 38. 字符串的排列 ——【Leetcode每日一題】

    (搜索) 劍指 Offer 38. 字符串的排列 ——【Leetcode每日一題】

    難度:中等 輸入一個(gè)字符串,打印出該字符串中字符的所有排列。 你可以以任意順序返回這個(gè)字符串?dāng)?shù)組,但里面 不能有重復(fù)元素 。 示例: 輸入:s = “abc” 輸出:[“abc”,“acb”,“bac”,“bca”,“cab”,“cba”] 限制 : 1 = s 的長(zhǎng)度 = 8 ??思路:回溯 可以直接 暴力窮舉 ,但

    2024年02月12日
    瀏覽(29)
  • 【LeetCode-中等】劍指 Offer 36. 二叉搜索樹與雙向鏈表

    劍指 Offer 36. 二叉搜索樹與雙向鏈表 后序遍歷、二叉搜索樹 二叉搜索樹中的任一節(jié)點(diǎn)的 直接前驅(qū)為其左子樹的最右側(cè)節(jié)點(diǎn),直接后繼為其右子樹的最左側(cè)節(jié)點(diǎn) 。因此,可以通過這個(gè)關(guān)系來操作原來的二叉樹。 為了不影響深度較大的節(jié)點(diǎn)的判斷,使用后序遍歷。 Step1. 后序遍

    2024年02月13日
    瀏覽(20)
  • (搜索) 劍指 Offer 13. 機(jī)器人的運(yùn)動(dòng)范圍 ——【Leetcode每日一題】

    (搜索) 劍指 Offer 13. 機(jī)器人的運(yùn)動(dòng)范圍 ——【Leetcode每日一題】

    難度:中等 地上有一個(gè) m 行 n 列的方格,從坐標(biāo) [0,0] 到坐標(biāo) [m-1,n-1] 。一個(gè)機(jī)器人從坐標(biāo) [0, 0] 的格子開始移動(dòng),它每次可以向左、右、上、下移動(dòng)一格(不能移動(dòng)到方格外),也不能進(jìn)入行坐標(biāo)和列坐標(biāo)的數(shù)位之和大于 k 的格子。例如,當(dāng) k 為18時(shí),機(jī)器人能夠進(jìn)入方格

    2024年02月11日
    瀏覽(19)
  • 《劍指offer》(5)搜索算法、位運(yùn)算、模擬

    《劍指offer》(5)搜索算法、位運(yùn)算、模擬

    方法一: class Solution: ? ? def GetNumberOfK(self , nums: List[int], k: int) - int: ? ? ? ? #從兩邊開始找,找到之后記錄當(dāng)前位置 ? ? ? ? left = 0 ? ? ? ? right = len(nums) - 1 ? ? ? ? if k not in nums: ? ? ? ? ? ? return 0 ? ? ? ? start = len(nums) - 1 ? ? ? ? end = 0 ? ? ? ? while left = right: ? ? ?

    2024年02月14日
    瀏覽(21)
  • 【LeetCode: 劍指 Offer II 089. 房屋偷盜(打家竊舍) | 暴力遞歸=>記憶化搜索=>動(dòng)態(tài)規(guī)劃】

    【LeetCode: 劍指 Offer II 089. 房屋偷盜(打家竊舍) | 暴力遞歸=>記憶化搜索=>動(dòng)態(tài)規(guī)劃】

    ??作者簡(jiǎn)介:碩風(fēng)和煒,CSDN-Java領(lǐng)域新星創(chuàng)作者??,保研|國(guó)家獎(jiǎng)學(xué)金|高中學(xué)習(xí)JAVA|大學(xué)完善JAVA開發(fā)技術(shù)棧|面試刷題|面經(jīng)八股文|經(jīng)驗(yàn)分享|好用的網(wǎng)站工具分享?????? ??座右銘:人生如棋,我愿為卒,行動(dòng)雖慢,可誰曾見我后退一步??????? 劍指 Offer II 089. 房屋偷盜

    2024年02月02日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包