Tag Archives: DFS

LeetCode Construct Binary Tree from Preorder and Inorder Traversal

105. Construct Binary Tree from Preorder and Inorder Traversal

Given preorder and inorder traversal of a tree, construct the binary tree.

Note:
You may assume that duplicates do not exist in the tree.

For example, given

preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]

Return the following binary tree:

    3
   / \
  9  20
    /  \
   15   7

根据树的先序遍历和中序遍历结果,重构这棵树。 其实大学的时候就有这样的作业,如果在纸上做,还是很简单的,但要实现成代码,稍微有点难理清这里的关系。 我们先来看一个纸上的解题过程,假设有下面这样一棵树:

        3
     /     \
    9       20
  /  \     /   \
 1    2  15    17
  • 先序遍历结果为:3, 9, 1, 2, 20, 15, 17
  • 中序遍历结果为:1, 9, 2, 3, 15, 20, 17

首先我们可以根据先序遍历结果找到根节点3,然后在中序遍历中看看3所处的位置,那么3左边的就是左孩子节点,右边的就是右孩子节点。我们在中序遍历中看看3左边有3个节点,说明3的左子树共有3个节点,同理右子树有3个节点。所以我们在先序遍历中也能知道3后面的3个节点是左子树,再后面3个节点是右子树,这样就把两个遍历结果分成了两部分:

  • 先序遍历结果为:3, 9, 1, 2, 20, 15, 17
  • 中序遍历结果为:1, 9, 2, 3, 15, 20, 17

在红色部分递归就是3的左子树,在蓝色部分递归就是3的右子树。 纸上解题好说,但是代码实现,我开始还把自己搞糊涂了,代码很复杂,后来参考了这位大神的博客,代码好简洁易懂,赞一个:

class Solution {
private:
    TreeNode* dfs(vector<int>& preorder, vector<int>& inorder, int preL, int preR, int inL, int inR, unordered_map<int, size_t>& hash)
    {
        if (preL > preR || inL > inR)
            return NULL;
        TreeNode* root = new TreeNode(preorder[preL]);
        size_t idx = hash[root->val];
        root->left = dfs(preorder, inorder, preL + 1, idx – inL + preL, inL, idx – 1, hash);
        root->right = dfs(preorder, inorder, idx – inL + preL + 1, preR, idx + 1, inR, hash);
        return root;
    }
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
    {
        if (preorder.size() == 0)
            return NULL;
        unordered_map<int, size_t> hash;
        for (size_t i = 0; i < inorder.size(); ++i) {
            hash[inorder[i]] = i;
        }
        return dfs(preorder, inorder, 0, preorder.size() – 1, 0, inorder.size() – 1, hash);
    }
};


本代码提交AC,用时16MS。
代码中有两点需要注意的,一是为了在中序遍历中快速找到根节点,提前对中序遍历结果hash了,因为题目中说了不会有重复元素;二是在dfs递归的时候,要算好下标的起止位置,一定不要弄错了,特别是preorder在左右子树中的起止位置。

LeetCode Word Search

79. Word Search

Given a 2D board and a word, find if the word exists in the grid.

The word can be constructed from letters of sequentially adjacent cell, where “adjacent” cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.

Example:

board =
[
  ['A','B','C','E'],
  ['S','F','C','S'],
  ['A','D','E','E']
]

Given word = "ABCCED", return true.
Given word = "SEE", return true.
Given word = "ABCB", return false.

Constraints:

  • board and word consists only of lowercase and uppercase English letters.
  • 1 <= board.length <= 200
  • 1 <= board[i].length <= 200
  • 1 <= word.length <= 10^3

给定一个字符面板和一个单词,问能否在该面板中搜索到该单词,搜索路径只能水平或垂直。 简单的深度搜索题,首先找到第一个字符的起始位置,然后深度往该字符的上下左右搜,只要有一个true就返回true,否则重置标记位,返回false。 完整代码如下:

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

本代码提交AC,用时9MS,击败95.63%的人。

LeetCode Flatten Binary Tree to Linked List

114. Flatten Binary Tree to Linked List

Given a binary tree, flatten it to a linked list in-place.

For example, given the following tree:

    1
   / \
  2   5
 / \   \
3   4   6

The flattened tree should look like:

1
 \
  2
   \
    3
     \
      4
       \
        5
         \
          6

把一棵二叉树展开成一个链表,链表还是借助树的数据结构,只不过是借用了树的右孩子指针作为链表的指针。 仔细观察发现新的链表的顺序和树的先序遍历的顺序一致,如果能使用额外的空间,则先序遍历后把节点存到数组中,然后依次链接起来。 如果不使用额外空间,则只能想办法在DFS时就建立好链接关系。先序遍历的顺序是根左右,但是这题为了方便,我们先对右孩子建立链表,然后把右孩子接到父亲的左孩子的最右下角的节点上。比如上图中,我们建立好5->6的链表之后,需要把它接到4号节点的右边。

         1
        /
       2
      / \
     3   4
          \
           5
            \
             6

所以针对右孩子,我们需要根据父节点找到父节点的左子树的最右下角的节点。但是针对左孩子时,因为此时右孩子已经建立好链表并且接到了左孩子正确的位置上,所以只需要把左孩子接到父亲的右孩子位置,并把原来的左孩子置空,下图就是把上图1的左子树放到了右边,左边置为空。

   1
     \
       2
      / \
     3   4
          \
           5
            \
             6

完整代码如下:

class Solution2 {
public:
    void dfs(TreeNode* par, TreeNode* cur)
    {
        if (cur == NULL)
            return;
        if (par) {
            if (cur == par->right) {
                if (par->left) {
                    TreeNode* tmp = par->left;
                    while (tmp->right)
                        tmp = tmp->right;
                    tmp->right = cur;
                    par->right = NULL;
                }
            }
            else {
                par->right = cur;
                par->left = NULL;
            }
        }
        if (cur->right)
            dfs(cur, cur->right);
        if (cur->left)
            dfs(cur, cur->left);
    }
    void flatten(TreeNode* root) { dfs(NULL, root); }
};

本代码提交AC,用时6MS。
还有一种思路比这简单,上面的解法需要while循环查找左兄弟的最右下角的节点,如果我们在DFS中直接返回尾节点,就不需要while查找了。
假设某节点的左右子树T(root->left)和T(root->right)已经flatten成linked list了:
1
/    \
2     5
\       \
3      6 <- rightTail
\
4  <- leftTail
如何将root、T(root->left)、T(root->right) flatten成一整个linked list?显而易见:
leftTail->right = root->right;
root->right = root->left;
root->left = NULL;
这里需要用到已经flatten的linked list的尾部元素leftTail, rightTail。所以递归返回值应该是生成的整个linked list的尾部。
代码如下:

class Solution {
public:
    TreeNode* dfs(TreeNode* root)
    {
        if (!root)
            return NULL;
        TreeNode* leftTail = dfs(root->left);
        TreeNode* rightTail = dfs(root->right);
        if (root->left) {
            leftTail->right = root->right;
            root->right = root->left;
            root->left = NULL;
        }
        if (rightTail)
            return rightTail;
        if (leftTail)
            return leftTail;
        return root;
    }
    void flatten(TreeNode* root) { dfs(root); }
};

本代码提交AC,用时6MS。

LeetCode Populating Next Right Pointers in Each Node II

117. Populating Next Right Pointers in Each Node II

Given a binary tree

struct Node {
  int val;
  Node *left;
  Node *right;
  Node *next;
}

Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.

Initially, all next pointers are set to NULL.

Follow up:

  • You may only use constant extra space.
  • Recursive approach is fine, you may assume implicit stack space does not count as extra space for this problem.

Example 1:

Input: root = [1,2,3,4,5,null,7]
Output: [1,#,2,3,#,4,5,7,#]
Explanation: Given the above binary tree (Figure A), your function should populate each next pointer to point to its next right node, just like in Figure B. The serialized output is in level order as connected by the next pointers, with '#' signifying the end of each level.

Constraints:

  • The number of nodes in the given tree is less than 6000.
  • -100 <= node.val <= 100

本题在LeetCode Populating Next Right Pointers in Each Node的基础上,扩展了二叉树的形式,并不要求二叉树一定是满二叉树(题中的完全二叉树),而是一个一般的二叉树。 这个时候就会遇到一些问题,比如下面的二叉树。

         1
       /  \
      2    3
     / \    \
    4   5    7
   /          \
  8            9

如果还按原来的先左孩子后右孩子的DFS,则第一次深度遍历完之后是这样的:

         1
       /  \
      2 -> 3
     / \    \
    4 ->5    7
   /          \
  8            9

此时要找8的next时就比较麻烦,因为在上一层到5时断了,没有5->7,所以找不到9号节点。所以需要修改为先对右孩子遍历,再对左孩子遍历,这样父亲一层的next就都完备了。 另外代码中还统一了child是左孩子和右孩子的代码,都是在父亲一层不断找next,直到找到合法next或者NULL。不过针对右孩子时,需要注意,为了不让其next指向左兄弟,增加了tmp != parent的约束。 完整代码如下:

class Solution {
public:
    void dfs(TreeLinkNode* child, TreeLinkNode* parent)
    {
        if (child == NULL)
            return;
        if (parent) {
            TreeLinkNode* tmp = parent;
            while (tmp) {
                if (tmp != parent && tmp->left && child != tmp->left) {
                    child->next = tmp->left;
                    break;
                }
                if (tmp->right && child != tmp->right) {
                    child->next = tmp->right;
                    break;
                }
                tmp = tmp->next;
            }
        }
        dfs(child->right, child);
        dfs(child->left, child);
    }
    void connect(TreeLinkNode* root) { dfs(root, NULL); }
};

本代码提交AC,用时32MS。

二刷。简单易懂但是比较啰嗦的代码:

class Solution {
public:
	void point2right(Node* par, Node* cur) {
		if (cur == NULL)return;

		if (par != NULL) {
			if (cur == par->left) {
				if (par->right != NULL) {
					cur->next = par->right;
				}
				else {
					Node* tmp = par->next;
					while (tmp != NULL) {
						if (tmp->left != NULL) {
							cur->next = tmp->left;
							break;
						}
						else if (tmp->right != NULL) {
							cur->next = tmp->right;
							break;
						}
						tmp = tmp->next;
					}
				}
			}
			else {
				// 和上面一段是一样的
				Node* tmp = par->next;
				while (tmp != NULL) {
					if (tmp->left != NULL) {
						cur->next = tmp->left;
						break;
					}
					else if (tmp->right != NULL) {
						cur->next = tmp->right;
						break;
					}
					tmp = tmp->next;
				}
			}
		}
		point2right(cur, cur->right);
		point2right(cur, cur->left);
	}
	Node* connect(Node* root) {
		if (root == NULL || (root->left == NULL && root->right == NULL))return root;
		point2right(NULL, root);
		return root;
	}
};

这一题的关键是要先递归右子树,再递归左子树。本代码提交AC,用时16MS。

LeetCode Populating Next Right Pointers in Each Node

116. Populating Next Right Pointers in Each Node

You are given a perfect binary tree where all leaves are on the same level, and every parent has two children. The binary tree has the following definition:

struct Node {
  int val;
  Node *left;
  Node *right;
  Node *next;
}

Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.

Initially, all next pointers are set to NULL.

Follow up:

  • You may only use constant extra space.
  • Recursive approach is fine, you may assume implicit stack space does not count as extra space for this problem.

Example 1:

Input: root = [1,2,3,4,5,6,7]
Output: [1,#,2,3,#,4,5,6,7,#]
Explanation: Given the above perfect binary tree (Figure A), your function should populate each next pointer to point to its next right node, just like in Figure B. The serialized output is in level order as connected by the next pointers, with '#' signifying the end of each level.

Constraints:

  • The number of nodes in the given tree is less than 4096.
  • -1000 <= node.val <= 1000

本题要给二叉树的每个节点添加next指针,指向它的右兄弟,如果没有右兄弟,则为NULL。 本题使用层次遍历可以很容易解决,但是需要使用额外的空间,不符合题目要求。 根据题目中的示意图,很明显如果节点是父亲的左孩子,则其next指向父亲的右孩子;但是如果节点是父亲的右孩子,则next指向需要跨界,不太好办,经题解提示,这种情况下,next指向父亲的next的左孩子,真是巧妙呀。所以可以用DFS完成本题,代码如下:

class Solution {
public:
    void dfs(TreeLinkNode* child, TreeLinkNode* parent)
    {
        if (child == NULL)
            return;
        if (parent) {
            if (child == parent->left)
                child->next = parent->right;
            else if (parent->next)
                child->next = parent->next->left;
        }
        dfs(child->left, child);
        dfs(child->right, child);
    }
    void connect(TreeLinkNode* root) { dfs(root, NULL); }
};

本代码提交AC,用时26MS。

LeetCode Serialize and Deserialize BST

LeetCode Serialize and Deserialize BST Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment. Design an algorithm to serialize and deserialize a binary search tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary search tree can be serialized to a string and this string can be deserialized to the original tree structure. The encoded string should be as compact as possible. Note: Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms should be stateless.


本题要序列化和反序列化二叉搜索树。因为二叉搜索树属于二叉树,所以可以直接用LeetCode Serialize and Deserialize Binary Tree对普通二叉树的序列化和反序列化方法。但是二叉搜索树又有其特殊性,即左孩子小于等于根节点,根节点小于等于右孩子。所以如果知道树中有哪些数,通过插入的方法就可以构造好二叉搜索树。 首先还是根据层次遍历或者树的先序遍历得到树的序列化表示,那么序列化的第一个数就是根节点了。反序列化时,依次插入后续的节点构成一棵二叉搜索树就好了。但是数值插入的顺序不能乱,比如下图,虽然确定了根节点是1,如果先插入了4号节点,再插入3号节点,则反序列化得到的树就不是原来的树了。为了保证序列化到的数值顺序正确,可以使用层次遍历或者树的先序遍历。 完整代码如下: [cpp] class Codec { public: // Encodes a tree to a single string. string serialize(TreeNode* root) { if (root == NULL)return ""; string ans = to_string(root->val); if (root->left) ans += ","+serialize(root->left); if (root->right) ans += ","+serialize(root->right); return ans; } void insert(TreeNode* root, TreeNode* node) { if (node->val < root->val) { if (root->left == NULL)root->left = node; else insert(root->left, node); } else { if (root->right == NULL)root->right = node; else insert(root->right, node); } } // Decodes your encoded data to tree. TreeNode* deserialize(string data) { if (data == "")return NULL; TreeNode* root = NULL; for (int start = 0, end = 0; end <= data.size(); ++end) { if (data[end] == ‘,’ || end == data.size()) { TreeNode* node = new TreeNode(atoi(data.substr(start, end – start).c_str())); if (root == NULL)root = node; else insert(root, node); start = end + 1; } } return root; } }; [/cpp] 本代码提交AC,用时26MS。]]>

LeetCode Battleships in a Board

LeetCode Battleships in a Board Given an 2D board, count how many different battleships are in it. The battleships are represented with 'X's, empty slots are represented with '.'s. You may assume the following rules:

  • You receive a valid board, made of only battleships or empty slots.
  • Battleships can only be placed horizontally or vertically. In other words, they can only be made of the shape 1xN (1 row, N columns) or Nx1 (N rows, 1 column), where N can be of any size.
  • At least one horizontal or vertical cell separates between two battleships – there are no adjacent battleships.
Example:
X..X
...X
...X
In the above board there are 2 battleships. Invalid Example:
...X
XXXX
...X
This is an invalid board that you will not receive – as battleships will always have a cell separating between them. Follow up: Could you do it in one-pass, using only O(1) extra memory and without modifying the value of the board?
这一题的题意有点难懂,要问一个面板上有多少个舰队,注意是舰队,而不是单个的战舰。比如第一个例子中,为什么有两个舰队呢,左上角单独的X是一个舰队,右边的一列是另一个舰队,所以一共有两个舰队。 题目还限制了舰队只可能是横向或者纵向排列的,而且两个舰队之间至少有一个空位.隔开。 因为题中说所有测试数据都是合法的,且两个舰队之间至少有一个空位.隔开,所以可以用深搜DFS找有多少个X连成的区域,就有多少个舰队。完整代码如下: [cpp] class Solution { public: void dfs(vector<vector<char>>& board, vector<vector<char>>& mark, int i, int j) { if (mark[i][j] == 1)return; if (board[i][j] == ‘.’)return; mark[i][j] = 1; if (i – 1 >= 0) { dfs(board, mark, i – 1, j); } if (i + 1 < board.size()) { dfs(board, mark, i + 1, j); } if (j – 1 >= 0) { dfs(board, mark, i, j – 1); } if (j + 1 < board[i].size()) { dfs(board, mark, i, j + 1); } } int countBattleships(vector<vector<char>>& board) { int ans = 0; vector<vector<char>> mark(board.size(), vector<char>(board[0].size(), 0)); for (int i = 0; i < board.size(); ++i) { for (int j = 0; j < board[i].size(); ++j) { if (mark[i][j] == 0 && board[i][j] == ‘X’) { ++ans; dfs(board, mark, i, j); } } } return ans; } }; [/cpp] 本代码提交AC,用时3MS。 Follow up中提到能否只用O(1)空间,且one-pass,网上题解提到,一个合法舰队的起始点的左边和上边肯定是空位.,否则这个X就会和其左边或者上边的X组成一个更大的舰队。所以我们只需要找面板中其左边和上边是.的X的个数。完整代码如下: [cpp] class Solution2 { public: int countBattleships(vector<vector<char>>& board) { int ans = 0; for (int i = 0; i < board.size(); ++i) { for (int j = 0; j < board[i].size(); ++j) { if (board[i][j] == ‘X’) { if ((i == 0 || board[i – 1][j] == ‘.’) && (j == 0 || board[i][j – 1] == ‘.’)) { ++ans; } } } } return ans; } }; [/cpp] 本代码提交AC,用时6MS。]]>

LeetCode Binary Tree Paths

257. Binary Tree Paths257. Binary Tree Paths

Given a binary tree, return all root-to-leaf paths.

Note: A leaf is a node with no children.

Example:

Input:    1  /   \ 2     3  \   5 Output: ["1->2->5", "1->3"] Explanation: All root-to-leaf paths are: 1->2->5, 1->3257. Binary Tree Paths

本题要求输出二叉树从根到叶子的所有路径,DFS题都做烂了,完整代码如下,不解释。

class Solution {
public:
    void dfs(vector<string>& ans, string cand, TreeNode* root)
    {
        cand += "->" + to_string(root->val);
        if (root->left == NULL && root->right == NULL) {
            ans.push_back(cand.substr(2));
            return;
        }
        if (root->left != NULL)
            dfs(ans, cand, root->left);
        if (root->right != NULL)
            dfs(ans, cand, root->right);
    }
    vector<string> binaryTreePaths(TreeNode* root)
    {
        vector<string> ans;
        if (root == NULL)
            return ans;
        dfs(ans, "", root);
        return ans;
    }
};

本代码提交AC,用时3MS。

LeetCode Sum Root to Leaf Numbers

129. Sum Root to Leaf Numbers

Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.

An example is the root-to-leaf path 1->2->3 which represents the number 123.

Find the total sum of all root-to-leaf numbers.

Note: A leaf is a node with no children.

Example:

Input: [1,2,3]
    1
   / \
  2   3
Output: 25
Explanation:
The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.
Therefore, sum = 12 + 13 = 25.

Example 2:

Input: [4,9,0,5,1]
    4
   / \
  9   0
 / \
5   1
Output: 1026
Explanation:
The root-to-leaf path 4->9->5 represents the number 495.
The root-to-leaf path 4->9->1 represents the number 491.
The root-to-leaf path 4->0 represents the number 40.
Therefore, sum = 495 + 491 + 40 = 1026.

睡前刷一题。把每一条从根到叶子的路径经过的数字拼起来组成一个数,求这些数的和。 简单的DFS题,不解释。完整代码如下:

class Solution {
public:
    void dfs(int& sum, int sub_sum, TreeNode* root)
    {
        if (root->left == NULL && root->right == NULL) {
            sum += (sub_sum * 10 + root->val);
            return;
        }
        if (root->left != NULL)
            dfs(sum, sub_sum * 10 + root->val, root->left);
        if (root->right != NULL)
            dfs(sum, sub_sum * 10 + root->val, root->right);
    }
    int sumNumbers(TreeNode* root)
    {
        if (root == NULL)
            return 0;
        int sum = 0;
        dfs(sum, 0, root);
        return sum;
    }
};

本代码提交AC,用时3MS。

LeetCode Path Sum II

113. Path Sum II

Given a binary tree and a sum, find all root-to-leaf paths where each path’s sum equals the given sum.

Note: A leaf is a node with no children.

Example:

Given the below binary tree and sum = 22,

      5
     / \
    4   8
   /   / \
  11  13  4
 /  \    / \
7    2  5   1

Return:

[
   [5,4,11,2],
   [5,8,4,5]
]

相比上一题LeetCode Path Sum更进一步,本题要把所有等于sum的路径记录下来,所以递归求解的时候要带着一个数组,把从根节点到当前节点的路径记录下来。常规题,完整代码如下:

class Solution {
public:
    void dfs(vector<vector<int> >& ans, vector<int>& path, int& target, int cur, TreeNode* root)
    {
        if (root->left == NULL && root->right == NULL) {
            if (cur + root->val == target) {
                path.push_back(root->val);
                ans.push_back(path);
                path.pop_back();
            }
            return;
        }
        if (root->left != NULL) {
            path.push_back(root->val);
            dfs(ans, path, target, cur + root->val, root->left);
            path.pop_back();
        }
        if (root->right != NULL) {
            path.push_back(root->val);
            dfs(ans, path, target, cur + root->val, root->right);
            path.pop_back();
        }
    }
    vector<vector<int> > pathSum(TreeNode* root, int sum)
    {
        vector<vector<int> > ans;
        if (root == NULL)
            return ans;
        vector<int> path;
        dfs(ans, path, sum, 0, root);
        return ans;
    }
};

本代码提交AC,用时16MS。
二刷。更简洁的代码,如下:

class Solution {
private:
    void dfs(vector<vector<int> >& ans, vector<int>& candidate, TreeNode* root, int sum)
    {
        candidate.push_back(root->val);
        sum -= root->val;
        if (root->left == NULL && root->right == NULL && sum == 0) {
            ans.push_back(candidate);
        }
        if (root->left != NULL)
            dfs(ans, candidate, root->left, sum);
        if (root->right != NULL)
            dfs(ans, candidate, root->right, sum);
        candidate.pop_back();
    }
public:
    vector<vector<int> > pathSum(TreeNode* root, int sum)
    {
        if (root == NULL)
            return {};
        vector<vector<int> > ans;
        vector<int> candidate;
        dfs(ans, candidate, root, sum);
        return ans;
    }
};

本代码提交AC,用时9MS。

三刷。更易读代码:

class Solution {
public:
	void dfs(TreeNode *root, vector<vector<int>> &ans, vector<int> &cand, int sum) {
		if (root->left == NULL && root->right == NULL && sum == 0) {
			ans.push_back(cand);
			return;
		}
		if (root->left != NULL) {
			cand.push_back(root->left->val);
			sum -= root->left->val;
			dfs(root->left, ans, cand, sum);
			sum += root->left->val;
			cand.pop_back();
		}
		if (root->right != NULL) {
			cand.push_back(root->right->val);
			sum -= root->right->val;
			dfs(root->right, ans, cand, sum);
			sum += root->right->val;
			cand.pop_back();
		}
	}
	vector<vector<int>> pathSum(TreeNode* root, int sum) {
		if (root == NULL)return {};
		vector<vector<int>> ans;
		vector<int> cand = { root->val };
		dfs(root, ans, cand, sum - root->val);
		return ans;
	}
};

本代码提交AC,用时12MS。