[牛 客 网 -Leetcode] # 树 中 sum-root-to-leaf-numbers

루트 노드에서 리프 노드 및 sum-root-to-leaf-numbers 로의 경로

제목 설명

숫자 0-9 만 포함하는 이진 트리가 주어지면 루트 노드에서 리프 노드까지의 각 경로를 숫자로 나타낼 수 있습니다.
예를 들어 루트 노드에서 리프 노드로의 경로는 1-> 2-> 3이면이 경로는 123으로 바뀝니다.
루트 노드에서 리프 노드까지의 모든 경로가 나타내는 숫자의 합을 찾습니다.
예 :
1↵ / ↵ 2 3
루트 노드에서 리프 노드로
의 경로 1-> 2 루트 노드에서 다음으로의 경로를 바꿉니다 . 숫자 12 의 리프 노드 1-> 3 숫자 13이 바뀌
므로 답은 12 + 13 = 25입니다.

0-9의 숫자 만 포함하는 이진 트리가 주어지면 각 루트-리프 경로는 숫자를 나타낼 수 있습니다.
예는 숫자 123을 나타내는 루트에서 리프 경로 1-> 2-> 3입니다.
모든 루트에서 리프 숫자의 총합을 찾으십시오.
예 : 1↵
/ ↵ 2 3
루트에서 리프 경로 1-> 2는 숫자 12를 나타냅니다.
루트에서 리프 경로 1-> 3은 숫자 13을 나타냅니다.
합계 = 12 + 13 = 25를 반환합니다.

예 1
입력

{1,0}

산출

10

예제 2
입력

{1, #, 5}

산출

15

문제 해결 아이디어

아이디어 1 : BFS

  • BFS에 따라 모든 리프 노드에서 루트 노드까지의 경로를 찾은 다음 추가합니다.
  • mp를 사용하여 모든 하위-> 부모의 매핑을 기록합니다. 이는 통합 검색 집합과 유사하므로 리프 노드에서 루트 노드로 이동할 수 있습니다.
    • 참고 : 상위에 여러 하위가있을 수 있고 매핑이 고유해야하므로 상위-> 하위 매핑을 생성 할 수 없습니다. 따라서 하위에서 상위로의 일대일 만 가능합니다.
  • leafNode 배열을 사용하여 모든 리프 노드를 저장하고 마지막으로 mp 매핑을 사용하여 각 리프 노드의 경로 합계를 찾고 누적합니다.
/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 * };
 */
#include "unordered_map"
class Solution {
    
    
public:
    int sumNumbers(TreeNode* root) {
    
    
        if(root == NULL) return 0;
        int res(0);
        queue<TreeNode*> myque;
        myque.push(root);
        //用于保存从叶节点到根节点的路径
        unordered_map<TreeNode*, TreeNode*> mp;  
        mp[root] = root;
        //用于保存所有的叶节点,方便遍历mp
        vector<TreeNode*> leafNode;
        
        while(!myque.empty()) {
    
    
            int size = myque.size();
            for(int i = 0; i < size; i ++) {
    
    
                TreeNode* temp = myque.front();
                myque.pop();
                //如果左右子树均为空,则添加进leafnode中
                if(!temp -> left && !temp -> right) {
    
    
                    leafNode.push_back(temp);
                }
                //如果有左右孩子,则添加 孩子->双亲 的映射
                if(temp -> left) {
    
    
                    myque.push(temp -> left);
                    mp[temp -> left] = temp;
                }
                if(temp -> right) {
    
    
                    myque.push(temp -> right);
                    mp[temp -> right] = temp;
                }
            }
        }
        //对每一个叶节点都计算其路径和,并累加
        for(auto node : leafNode) {
    
    
            int sum(0);  //记录每一个叶节点的路径和
            int temp(1);
            while(node != root) {
    
    
                sum += node -> val * temp;
                temp *= 10;
                node = mp[node];  //不断往根节点遍历
            }
            sum += root -> val * temp;  //最后加上根节点
            res += sum;
        }
        
        return res;
    }
};

아이디어 2 : 역 추적

  • 경로 : 트랙에 기록
  • 선택 목록 : 비어 있지 않은 왼쪽 및 오른쪽 하위 트리
  • 종료 조건 : 리프 노드에 도달 한 다음 누적
  • 참고 : 역 추적 방법이 트리의 경로 문제를 해결하기 전에 루트 노드를 경로에 추가해야합니다.
  • 보충, 누적 기능 사용 :
    • accumulate의 헤더 파일은 다음과 같습니다.#include <numeric>

    • 예를 들어 vector<int> vec배열의 경우 합계 :
      int sum = accumulate(vec.begin(), vec.end(), 0)
      누적 및 합계의 결과가 합계에 저장됩니다. 처음 두 매개 변수는 합계의 범위를 지정하고 세 번째 매개 변수는 누적의 초기 값을 지정합니다.

      accumulate를 사용하여 문자열 유형 벡터 컨테이너의 요소를 연결할 수도 있습니다.
      string sum = accumulate(v.begin() , v.end() , string(" "));
      이 함수 호출의 효과는 다음과 같습니다. 빈 문자열에서 시작하여 vec의 각 요소가 문자열에 연결됩니다.

/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 * };
 */
#include<numeric>
class Solution {
    
    
public:
    int sumNumbers(TreeNode* root) {
    
    
        if(root == NULL) return 0;
        int res(0);
        vector<int> track;
        
        //先把根节点添加进路径
        track.push_back(root -> val);
        backtrack(root, track, res);
        return res;
    }
    void backtrack(TreeNode* root, vector<int>& track, int& res) {
    
    
        if(root == NULL) return ;
        //叶子节点,则累加
        if(!root -> left && !root -> right) {
    
    
            int sum(0);  //对于每一个叶节点,记录其路径和
            for(int i = 0; i < track.size(); i ++) {
    
    
                sum = sum * 10 + track[i];
            }
            res += sum;
        }
        if(root -> left) {
    
    
            track.push_back(root -> left -> val);
            backtrack(root -> left, track, res);
            track.pop_back();
        }
        if(root -> right) {
    
    
            track.push_back(root -> right -> val);
            backtrack(root -> right, track, res);
            track.pop_back();
        }
    }
};

아이디어 3 : DFS

  • DFS와 역 추적은 DFS가 업데이트 된 매개 변수를 다음 단계로 직접 가져온다는 점을 제외하면 비슷한 방식으로 작성됩니다. 역 추적은 먼저 업데이트 한 다음 철회하는 것이지만 둘 다 선택하는 것입니다.
  • DFS는 역 추적과 동일하며 트리의 경로와 문제에 직면했을 때 먼저 결과에 루트 노드를 추가해야합니다.
/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 * };
 */
#include<numeric>
class Solution {
    
    
public:
    int sumNumbers(TreeNode* root) {
    
    
        if(root == NULL) return 0;
        int res = 0; //用于保存最终结果
        int sum = root -> val;  //用于记录每个叶节点的路径和,初始为根节点的值
        dfs(root, res, sum);
        return res;
    }
    void dfs(TreeNode* root, int& res, int sum) {
    
    
        if(root == NULL) return ;
        //如果是叶节点,则累加
        if(!root -> left && !root -> right) {
    
    
            res += sum;
        }
        //两个选择:左子树和右子树
        if(root -> left) {
    
    
            dfs(root -> left, res, sum * 10 + root -> left -> val);
        }
        if(root -> right) {
    
    
            dfs(root -> right, res, sum * 10 + root -> right -> val);
        }
    }
};

추천

출처blog.csdn.net/cys975900334/article/details/106896402