LeetCodeバイナリツリーの再帰と4つのトピック:どのように再帰関数の戻り値を使用する方法

例1:LeetCode 257タイトル:バイナリーツリー全てのパス

ポータル:すべてのパス257バイナリツリー

バイナリツリーを考えると、ルート・ノードからのすべてのパスは、リーフノードを返します。

説明:リーフノードは、ノードが子ノードを持たないです。

例:

输入:

   1
 /   \
2     3
 \
  5

输出: ["1->2->5", "1->3"]

解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3

要件:ルートノードから二分木指定されたパスのすべてのリーフノードを表す文字列を返します。

キー:理解が深さのアプリケーション内で最初の検索を「バックトラック」。

1つのアイデア:の使用再帰が課金時に完了し、記録パスの方法は、リーフノードに来ます。

Pythonコード:特に注意を==:伝送パラメータを経由して、明示的なバックトラック・プロセスはありません==です

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
# 257. 二叉树的所有路径
# 给定一个二叉树,返回所有从根结点到叶子结点的路径。


class Solution:

    # 深度优先遍历,我感觉最好理解
    # 参考:https://leetcode.com/problems/binary-tree-paths/discuss/68258/Accepted-Java-simple-solution-in-8-lines

    def binaryTreePaths(self, root):
        """
        :type root: TreeNode
        :rtype: List[str]
        """

        res = []
        if root is None:
            return res
        self.__helper(root, '', res)
        return res

    def __helper(self, node, pre, res):
        if node.left is None and node.right is None:
            res.append(pre + str(node.val))
            return
        # 特别注意:通过参数传递的方式,就没有显式的回溯的过程了
        if node.left:
            self.__helper(node.left, pre + str(node.val) + '->', res)
        if node.right:
            self.__helper(node.right, pre + str(node.val) + '->', res)

アイデア2:使用深さ優先探索、道をバックトラック、パスをスタックからポップすることが、後に終了する:必ず覚えておいてください

Pythonコード:

# Definition for a binary tree node.
class TreeNode(object):
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None


class Solution(object):
    def binaryTreePaths(self, root):
        """
        :type root: TreeNode
        :rtype: List[str]
        """

        res = []
        if root is None:
            return res
        path = []
        self.__helper(root, path, res)
        return res

    def __helper(self, node, path, res):
        """
        :param node:
        :param path: 沿途经过的结点值组成的列表
        :param res: 存放最终结果的变量
        :return:
        """
        if node is None:
            return
        path.append(str(node.val))
        if node.left is None and node.right is None:
            # 可以结算了
            res.append("->".join(path))
            return
        if node.left:
            self.__helper(node.left, path, res)

            # 【重点】:回溯的时候,要记得弹出
            # 左边结点都看过了,所以 path 要弹出
            path.pop()

        if node.right:
            self.__helper(node.right, path, res)

            # 【重点】:回溯的时候,要记得弹出
            # 右边结点都看过了,所以 path 要弹出
            path.pop()

これらの2つの方法は、実際に、それはまた、補助の助けを借りずに機能することができ、補助機能で使用され、元の関数に直接再帰行います。

414598-891b0f53f10ddf20.jpg
LeetCode 257タイトル:すべてのパスバイナリツリー

Pythonコード:

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None


class Solution:

    def binaryTreePaths(self, root):
        """
        :type root: TreeNode
        :rtype: List[str]
        """
        res = []

        if root is None:
            return []

        if root.left is None and root.right is None:
            res.append(str(root.val))
            return res

        left_paths = self.binaryTreePaths(root.left)
        for lpath in left_paths:
            res.append(str(root.val) + '->' + lpath)

        right_paths = self.binaryTreePaths(root.right)
        for rpath in right_paths:
            res.append(str(root.val) + '->' + rpath)

        return res

演習1:LeetCode 113タイトル:総経路II

ポータル:英語URL:113 IIパス合計、中国のウェブサイト:113パスIIの合計

バイナリツリーとターゲット所与のリーフノードのルートノードからのすべてのパスの合計を検索することが指定されたターゲットとパスと同じです。

説明:リーフノードは、ノードが子ノードを持たないです。

例:
次のバイナリツリー、およびターゲットを考えるとsum = 22

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

戻り値:

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

アイデア:先行順走査。ルーチンは、ヘルパー関数を使用することです。、中央のパスを保存道路がポップアップを覚えて、それから、最後に行けばPythonはメソッドのリストをコピー:
1list(path) ;
2path * 1 ; 3、 。
path[:]

Pythonコード:

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

# 使用 dfs 来解决

# 113. 路径总和 II
# 给定一个二叉树和一个目标和,找到所有从根结点到叶子结点路径总和等于给定目标和的路径。
# 解法 1 和 解法 2 是一回事。
class Solution(object):
    def pathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: List[List[int]]
        """

        results = []
        self.__dfs([], root, sum, results)
        return results

    def __dfs(self, path, root, sum, results):
        if root is None:
            return
        if root.left is None and root.right is None and root.val == sum:
            result = []
            result.extend(path)
            result.append(root.val)
            results.append(result)
            return
        path.append(root.val)
        if root.left:
            self.__dfs(path, root.left, sum - root.val, results)
        if root.right:
            self.__dfs(path, root.right, sum - root.val, results)
        # 这一步很关键
        path.pop()

演習2:LeetCode 129タイトル:数字のリーフノード和のルーツ

ポータル:葉ノードのルーツと数字の合計

バイナリツリー与え、格納されている各ノードの0-9ルートから各リーフノードに、数がパスの数を表します。

例えば、リーフ・ノードへのルートからのパス1->2->3デジタルを表します123

すべての数値の和によって生成されたリーフノードへのルートから算出しました。

説明:リーフノードは、ノードが子ノードを持たないです。

例1:

输入: [1,2,3]
    1
   / \
  2   3
输出: 25
解释:
从根到叶子节点路径 1->2 代表数字 12.
从根到叶子节点路径 1->3 代表数字 13.
因此,数字总和 = 12 + 13 = 25.

例2:

输入: [4,9,0,5,1]
    4
   / \
  9   0
 / \
5   1
输出: 1026
解释:
从根到叶子节点路径 4->9->5 代表数字 495.
从根到叶子节点路径 4->9->1 代表数字 491.
从根到叶子节点路径 4->0 代表数字 40.
因此,数字总和 = 495 + 491 + 40 = 1026.

要件:二分木を考えると、各ノードは唯一の数字0-9を含み、各リーフノードへのルートからのパスは数値として表され、これらの番号を見つけることができます。

Javaコード1:パスを使用して、従来の再帰的な解後戻り。

// https://leetcode-cn.com/problems/sum-root-to-leaf-numbers/description/

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

// 我的思路:使用深度优先遍历,遍历到根结点的时候,把数字加一加
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int x) {
        val = x;
    }
}

public class Solution {

    private List<String> result = new ArrayList<>();

    private void sumNumbers(TreeNode node, String path) {
        if (node == null) {
            return;
        }

        path = path + node.val;
        if (node.left == null && node.right == null) {
            // 才是叶子结点,执行我们的逻辑
            result.add(path);
            return;
        }
        sumNumbers(node.left, path);
        sumNumbers(node.right, path);
    }

    private int convert() {
        int sum = 0;
        for (String s : result) {
            sum += Integer.parseInt(s);
        }
        return sum;
    }

    public int sumNumbers(TreeNode root) {
        if (root == null) {
            return 0;
        }
        sumNumbers(root, "");
        return convert();
    }

    public static void main(String[] args) {
        TreeNode n1 = new TreeNode(1);
        TreeNode n2 = new TreeNode(2);
        TreeNode n3 = new TreeNode(3);
        n1.left = n2;
        n1.right = n3;

        Solution solution = new Solution();
        int result = solution.sumNumbers(n1);
        System.out.println("得到的结果:" + result);
    }
}

Pythonコード2(推奨):(再帰的)前CUMSUMにこの概念を使用して、ルート・ノードを横断するために始めた、コードを書くことは非常に簡単で、CUMSUMてきました。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None


class Solution:
    def sumNumbers(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        res = []
        self.__dfs(root, 0, res)
        return sum(res)

    # Python 中对于基础的数据类型是值传递,即复制
    def __dfs(self, root, cum_sum, res):
        if root is None:
            return None
        if root.left is None and root.right is None:
            # 结算
            res.append(cum_sum * 10 + root.val)
            return
        self.__dfs(root.left, cum_sum * 10 + root.val, res)
        self.__dfs(root.right, cum_sum * 10 + root.val, res)

Javaコード3:

// https://leetcode-cn.com/problems/sum-root-to-leaf-numbers/description/


import java.util.ArrayList;
import java.util.List;

// 我的思路:这个写法,画个图就非常清晰了,抓住二叉树的特点

public class Solution2 {

    private int sumNumbers(TreeNode node, int cumsum) {
        if (node == null) {
            return 0;
        }
        cumsum = 10 * cumsum + node.val;
        if (node.left == null && node.right == null) {
            return cumsum;
        }
        return sumNumbers(node.left, cumsum) + sumNumbers(node.right, cumsum);
    }


    public int sumNumbers(TreeNode root) {
        if (root == null) {
            return 0;
        }
        return sumNumbers(root, 0);
    }

    public static void main(String[] args) {
        // write your code here
        TreeNode n1 = new TreeNode(1);
        TreeNode n2 = new TreeNode(2);
        TreeNode n3 = new TreeNode(3);
        n1.left = n2;
        n1.right = n3;

        Solution2 solution2 = new Solution2();
        int result = solution2.sumNumbers(n1);
        System.out.println("得到的结果:" + result);
    }
}

そこソリューションでもあり、元のバイナリツリーノードの値を変更します。

Pythonコード:

# 129. 求根到叶子结点数字之和
# 给定一个二叉树,它的每个结点都存放一个 0-9 的数字,每条从根到叶子结点的路径都代表一个数字。
# 例如,从根到叶子结点路径 1->2->3 代表数字 123。
# 计算从根到叶子结点生成的所有数字之和。
# 说明: 叶子结点是指没有子结点的结点。

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None


class Solution:

    def __init__(self):
        self.res = 0

    def sumNumbers(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if root is None:
            return 0
        if root.left:
            # 如果左边非空
            root.left.val += root.val * 10
        if root.right:
            # 如果右边非空
            root.right.val += root.val * 10
        # 如果左边右边都为空,就可以结算了
        if root.left is None and root.right is None:
            self.res += root.val
        # 前序遍历
        self.sumNumbers(root.left)
        self.sumNumbers(root.right)
        return self.res

(この節の終わり)

おすすめ

転載: blog.csdn.net/weixin_33836874/article/details/90885299