[Leetcode Road to Brushing Questions] Oferta Jianzhi (3) - Algoritmos de busca e retrocesso

Diretório de artigos

7 Algoritmos de busca e retrocesso

7.1 【BFS】Jianzhi Offer 32 - I - Imprimir árvore binária de cima para baixo

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

  Aqui, a travessia em largura é implementada com a ajuda de filas. Como os nós de cada camada precisam ser acessados ​​e essa camada de acesso só pode acessar a próxima camada, o primeiro a entrar primeiro a sair da fila pode ser considerados, e os nós de cada camada são adicionados à fila primeiro, e então Ao visitar os nós desta camada, suas subárvores esquerda e direita também são adicionadas à fila, de modo que após cada camada ser visitada, ela é seguida por os nós da próxima camada.

/**
 * 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】Jianzhi Offer 32 - II - Imprimir árvore binária II de cima para baixo

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

  Aqui, a travessia em largura é implementada com a ajuda de filas. Como os nós de cada camada precisam ser acessados ​​e essa camada de acesso só pode acessar a próxima camada, o primeiro a entrar primeiro a sair da fila pode ser considerados, e os nós de cada camada são adicionados à fila primeiro, e então Ao visitar os nós desta camada, suas subárvores esquerda e direita também são adicionadas à fila, de modo que após cada camada ser visitada, ela é seguida por os nós da próxima camada. A diferença da pergunta acima é que o número de cada camada deve ser armazenado como um vetor e, finalmente, retornar vários vetores.

/**
 * 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] [Fila de duas pontas] Oferta de ponteiro de espada 32 - III - Imprimir árvore binária III de cima para baixo

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

  Aqui, a travessia em largura é obtida por meio de filas duplas. Como os nós de cada camada precisam ser acessados ​​e essa camada de acesso só pode acessar a próxima camada, para camadas ímpares, a ordem de acesso é da esquerda para a direita, enquanto para camadas pares é da direita para a esquerda, então você pode fazer o seguinte:

  • Camada ímpar: os elementos da fila são retirados da esquerda para a direita, mas cada elemento primeiro pega sua subárvore esquerda e, em seguida, pega a subárvore direita e, em seguida, insere a partir do final da fila;
  • Camadas pares: os elementos da fila são retirados da direita para a esquerda, mas cada elemento é primeiro retirado de sua subárvore direita e depois da subárvore esquerda e, em seguida, inserido a partir do início da fila.

  Dessa forma, pode-se garantir que a ordem de cada camada esteja em zigue-zague quando conectadas.

/**
 * 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] Jianzhi Offer 26 - A subestrutura da árvore

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

  Aqui, cada nó de A é comparado com B. Se os nós forem iguais, verifique se suas subárvores esquerda e direita são iguais. Aqui, uma função personalizada é usada para determinar se A e B são relacionamentos inclusivos, ou seja, A contém B. A definição da função é a seguinte:

  • Se B estiver vazio, significa que todos os nós de B foram percorridos neste momento e B é uma subárvore de A;
  • Se B não estiver vazio e A estiver vazio, isso significa que todos os nós de A foram percorridos neste momento, mas B ainda possui nós, então B não é uma subárvore de A;
  • Se os nós de A e B são os mesmos neste momento, também é necessário julgar se suas subárvores esquerda e direita são as mesmas.
/**
 * 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 [Recursão] A espada refere-se à Oferta 27 - a imagem espelhada da árvore binária

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

  Troque diretamente as subárvores esquerda e direita de cada nó e, em seguida, retorne recursivamente.

/**
 * 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 [Recursão] [Ponteiro Duplo] Oferta de Ponteiro de Espada 28 - Árvore Binária Simétrica

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

  Use ponteiros duplos para julgar se é simétrico das subárvores esquerda e direita da árvore. Deve-se notar aqui que os ponteiros duplos devem estar vazios ao mesmo tempo. Se um estiver vazio primeiro, significa que a árvore binária é assimétrica Para mover para baixo simetricamente, por exemplo, l move-se para a esquerda r move-se para a direita, l move-se para a direita r move-se para a esquerda.

/**
 * 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] [Backtracking] [Pruning] Apontando para Oferta 12 - o caminho na matriz

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

  Aqui, primeiro encontramos a posição correspondente ao primeiro caractere da string na matriz e, em seguida, pesquisamos em profundidade a partir dessa posição para cima, para baixo, para a esquerda e para a direita até encontrarmos um caminho de pesquisa correspondente à conclusão da string, mas aqui precisamos definir algumas regras de ramificação de recorte encerrar pesquisas desnecessárias antecipadamente:

  • Se o acesso estiver fora dos limites, a busca precisa ser encerrada com antecedência;
  • Se os caracteres atualmente acessados ​​na matriz forem diferentes dos caracteres atualmente percorridos na string, a pesquisa precisa ser encerrada antecipadamente.

  Aqui, para evitar que os elementos da matriz sejam reutilizados, os elementos que foram visitados são atribuídos uniformemente como vazios e, quando essa rodada de pesquisa é concluída, a string é atribuída de volta para evitar afetar o julgamento.

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当前访问字符不一致时,需要提前终止搜索,返回false
        if(i>=row || i<0 || j>=col || j<0 || board[i][j]!=word[k]) return false;
        //字符串遍历到最后一个字符,说明找到了一条路径,返回true
        if(k==word.size()-1) return true;
        //避免矩阵重复访问,已访问的赋值为空
        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);
        //此轮搜索结束,已访问过的再赋值回去
        board[i][j] = word[k];
        return flag;
    }
};

7.8 【DFS】Jian Zhi Offer 13 - A amplitude de movimento do robô

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

  Use o DFS para resolver o problema. Embora o robô possa se mover para cima, para baixo, para a esquerda e para a direita, o cálculo final é quantas grades o robô pode alcançar, então você pode simplificar para cima, para baixo, para a esquerda e para a direita em duas ações, para baixo e à direita, e defina um array visit para registrar se cada grade é visitada. A dificuldade desta questão está em como calcular rapidamente a soma dos dígitos das coordenadas da linha e das colunas. Aqui podemos encontrar uma regra, assumindo que as coordenadas são 18, 19, 20, 21, 22, as somas dos dígitos são 9, 10, 2 respectivamente ,3,4, aqui se as coordenadas não forem múltiplas de 10, a soma dos dígitos aumenta em 1 à medida que o número de coordenadas aumenta e, quando atinge 20, a soma dos dígitos se torna diretamente 2, o que é 8 menor que a soma de dígitos de 19 e o mesmo As somas de dígitos das coordenadas físicas 29, 30 e 31 são 11, 3 e 4, respectivamente, portanto, as seguintes regras podem ser resumidas:

  • Se a coordenada não for múltipla de 10, adicione 1 à soma digital em relação à coordenada anterior;
  • Se as coordenadas forem múltiplos de 10. A soma dos dígitos é menos 8 da coordenada anterior.
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] [Recursão] A espada refere-se à Oferta 34 - o caminho com um certo valor na árvore binária

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

  Use o DFS para resolver o problema, primeiro percorra o nó raiz até um nó filho e, em seguida, percorra o outro. A dificuldade aqui é julgar com precisão se a soma desejada foi alcançada. As seguintes condições são necessárias no total:

  • A soma de val no caminho até agora é igual a target;
  • O nó atual é um nó folha, ou seja, os nós esquerdo e direito do nó estão todos vazios.
/**
 * 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] [Recursão] [Ponteiro duplo] Oferta de ponteiro de espada 36 - Árvore de pesquisa binária e lista duplamente vinculada

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

  Esta questão é, na verdade, transformar a árvore binária fornecida na saída de resultado da travessia em ordem e, em seguida, alterar os ponteiros das subárvores esquerda e direita durante a travessia em ordem para torná-la uma lista vinculada circular bidirecional. usa ponteiros duplos para construir uma lista encadeada circular, cabeça aponta para o início da lista encadeada circular, pré aponta para o nó de pré-ordem de cada nó visitado durante o processo de travessia em ordem, DFS é executado de acordo com o processo de in travessia de ordem, e ao percorrer para a subárvore inferior esquerda, comece a construir a lista encadeada. Neste momento, a subárvore esquerda deve ser a predecessora da raiz atual, então um ciclo é construído e, em seguida, volte para construir outro ciclos e, finalmente, conectar a cabeça e a cauda.

/*
// 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] A espada refere-se à Oferta 54 - o k-ésimo maior nó da árvore de busca binária

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

  Esta questão é encontrar o k-ésimo maior nó. O resultado da travessia em ordem da árvore de busca binária é classificado do menor para o maior, então é na verdade uma travessia em ordem inversa da árvore de busca binária. Toda vez que um elemento k– é percorrido, quando k é 0 é o resultado final.

/**
 * 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】Jianzhi Offer 55 - I - Profundidade da Árvore Binária

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

  Investigue a travessia em profundidade, pesquise de cima para baixo, adicione 1 ao dpt de profundidade atual se nenhum nó for encontrado e, finalmente, pegue o maior 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] Oferta de Ponteiro de Espada 55 - II - Árvore Binária Balanceada

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

  Usando o método bottom-up, primeiro julgue se o nó inferior atende à condição de uma árvore binária balanceada, caso contrário, atribua a altura atual a -1, de modo que aumente passo a passo de baixo para cima e, finalmente, precise apenas veja a altura do nó raiz é Quanto é suficiente, se você usar de cima para baixo, haverá alguns nós que calculam a altura várias vezes, o que aumentará a complexidade do tempo.

/**
 * 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 [Operação de bit] Jianzhi Offer 64 - Encontre 1+2+…+n

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

  A fórmula de soma é sum=n*(n+1)/2. Por que usar bool aqui? Na verdade, char também é bom, porque todos ocupam um byte, o que significa que uma matriz de n*(n+1) é construído. , e primeiro calcule o número total de bytes neste array, para a operação de divisão por 2, a operação de bit direto é suficiente.

class Solution {
    
    
public:
    int sumNums(int n) {
    
    
        bool ans[n][n+1];
        return sizeof(ans)>>1;
    }
};

7.15 [DFS] [Recursive] Jianzhi Offer 68 - I - O ancestral comum mais próximo da árvore de busca binária

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

  Essa questão precisa ser entendida, ou seja, o valor de x deve estar entre p e q, então ao percorrer em profundidade, basta comparar o valor do nó raiz atual com o valor de p e q. Se o valor do nó atual É maior que p e q, indicando que o ancestral comum mais próximo está na subárvore esquerda. Se o valor do nó atual for menor que p e q, indica que o ancestral comum mais próximo está na subárvore subárvore direita. Se nenhum for satisfeito, isso significa que o ancestral comum mais próximo foi encontrado no momento.

/**
 * 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] Espada refere-se à Oferta 68 - II - O ancestral comum mais próximo da árvore binária

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

  Este tópico é para encontrar o ancestral comum mais próximo em uma árvore binária geral. Primeiro, os critérios para julgar o ancestral comum devem ser esclarecidos. Existem três pontos a seguir:

  • (1) p e q estão em ambos os lados da árvore binária (isto é, um está na subárvore esquerda e o outro está na subárvore direita), então encontre o nó raiz mais próximo;
  • (2) p e q estão do mesmo lado da árvore binária (isto é, ambos na subárvore esquerda ou na subárvore direita), então encontre p ou q;

  O seguinte define ponteiros duplos esquerdo e direito para julgar se há p e q nas subárvores esquerda e direita do nó atual e fornece os seguintes critérios de julgamento:

  • (1) Se esquerda e direita não estiverem vazias, significa que p e q estão na subárvore esquerda e o outro está na subárvore direita, e retorna o nó raiz atual;
  • (2) Se esquerda estiver vazia e direita não estiver vazia, significa que tanto p quanto q estão na subárvore direita e retornam à direita;
  • (3) Se esquerda não estiver vazia e direita estiver vazia, significa que tanto p quanto q estão na subárvore esquerda, e esquerda é retornada.
/**
 * 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] [Simulação] Jianzhi Offer 37 - Árvore Binária Serializada

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

  Esta questão implementa principalmente duas funções, a saber, a serialização e desserialização da árvore binária, ou seja, uma determinada string se torna uma árvore binária ou uma determinada árvore binária se torna uma string. As ideias de implementação são apresentadas separadamente abaixo: (1) Árvore binária -
> A string
  é, na verdade, uma travessia em ordem da árvore binária e, em seguida, salva o valor de cada nó na string. A dificuldade está em como converter o inteiro em uma string, porque o valor aqui pode ser de vários dígitos ou negativo, então Uma função int_to_str() é definida aqui para converter um inteiro em uma string e, ao mesmo tempo, a função tree_to_str() é usada para converter uma árvore binária em uma string. Observe que uma vírgula ',' deve ser adicionado após cada valor.
(2) String -> árvore binária
  Isso é mais difícil. Primeiro, os caracteres na string devem ser convertidos em números. Isso é obtido por meio da função personalizada str_to_int(). A próxima etapa é construir um nó para cada valor gerado. Construa a árvore binária sequencialmente de acordo com a travessia em ordem. Depois que as preparações acima forem concluídas, o seguinte é cortar a string fornecida. O padrão de divisão é uma vírgula ','. A travessia significa que toda vez que uma vírgula é encontrada, é um nó e, em seguida, este nó pode ser inserido na árvore binária por meio das duas etapas acima.

/**
 * 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] [Backtracking] [Simulação] Jianzhi Offer 38 - Arranjo de strings

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

  A dificuldade dessa questão está em como garantir que os caracteres não sejam repetidos, e ao mesmo tempo garantir que não haja strings repetidas na string final obtida. Considerando que pode haver alguns caracteres repetidos na string original, primeiro execute a classificação da string original e, em seguida, defina uma matriz visitada para salvar se cada bit foi visitado e, ao percorrer em profundidade, para cada caractere visitado, também é necessário determinar se é um caractere repetido para evitar que caracteres repetidos sejam visitou várias vezes. Mas, no final, a mesma string é realmente obtida. Finalmente, após essa travessia, a string temporária tmp e visited deve retornar ao seu estado original.

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

おすすめ

転載: blog.csdn.net/qq_44528283/article/details/131650176