1. 程式人生 > >劍指Offer面試題:23.二叉樹中和為某一值的路徑

劍指Offer面試題:23.二叉樹中和為某一值的路徑

一、題目:二叉樹中和為某一值的路徑

題目:輸入一棵二叉樹和一個整數,打印出二叉樹中結點值的和為輸入整數的所有路徑。從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。例如輸入下圖中二叉樹和整數22,則打印出兩條路徑,第一條路徑包含結點10、12,第二條路徑包含結點10、5和7。

  二叉樹結點的定義如下:

    public class BinaryTreeNode
    {
        public int Data { get; set; }
        public BinaryTreeNode leftChild { get; set; }
        
public BinaryTreeNode rightChild { get; set; } public BinaryTreeNode(int data) { this.Data = data; } public BinaryTreeNode(int data, BinaryTreeNode left, BinaryTreeNode right) { this.Data = data; this.leftChild = left;
this.rightChild = right; } }

二、解題思路

2.1 核心步驟

  首先,通過下圖瞭解遍歷上圖中的二叉樹的過程:

  通過上圖可以總結出規律:

  (1)當用前序遍歷的方式訪問到某一結點時,我們把該結點新增到路徑上,並累加該結點的值。

  (2)如果該結點為葉結點並且路徑中結點值的和剛好等於輸入的整數,則當前的路徑符合要求,我們把它打印出來。如果當前結點不是葉結點,則繼續訪問它的子結點。

  (3)當前結點訪問結束後,遞迴函式將自動回到它的父結點。這裡要注意的是:在函式退出之前要在路徑上刪除當前結點並減去當前結點的值,以確保返回父結點時路徑剛好是從根結點到父結點的路徑。

2.2 程式碼實現

    public static void FindPath(BinaryTreeNode root, int expectedSum)
    {
        if (root == null)
        {
            return;
        }

        int currentSum = 0;
        List<int> path = new List<int>();
        FindPath(root, expectedSum, path, ref currentSum);
    }

    private static void FindPath(BinaryTreeNode root, int expectedSum, List<int> path, ref int currentSum)
    {
        currentSum += root.Data;
        path.Add(root.Data);
        // 如果是葉結點,並且路徑上結點的和等於輸入的值
        // 打印出這條路徑
        bool isLeaf = root.leftChild == null && root.rightChild == null;
        if (isLeaf && currentSum == expectedSum)
        {
            foreach (int data in path)
            {
                Console.Write("{0}\t", data);
            }
            Console.WriteLine();
        }

        // 如果不是葉結點,則遍歷它的子結點
        if (root.leftChild != null)
        {
            FindPath(root.leftChild, expectedSum, path, ref currentSum);
        }

        if (root.rightChild != null)
        {
            FindPath(root.rightChild, expectedSum, path, ref currentSum);
        }

        // 在返回到父結點之前,在路徑上刪除當前結點,
        // 並在currentSum中減去當前結點的值
        path.Remove(root.Data);
        currentSum -= root.Data;
    }

三、單元測試

3.1 測試用例

  (1)輔助方法的封裝

    private static void TestPortal(string testName, BinaryTreeNode root, int expectedSum)
    {
        if (!string.IsNullOrEmpty(testName))
        {
            Console.WriteLine("{0} begins:", testName);
        }

        FindPath(root, expectedSum);

        Console.WriteLine();
    }

    private static void SetSubTreeNode(BinaryTreeNode root, BinaryTreeNode lChild, BinaryTreeNode rChild)
    {
        if (root == null)
        {
            return;
        }

        root.leftChild = lChild;
        root.rightChild = rChild;
    }

    private static void ClearUpTreeNode(BinaryTreeNode root)
    {
        if (root != null)
        {
            BinaryTreeNode left = root.leftChild;
            BinaryTreeNode right = root.rightChild;

            root = null;

            ClearUpTreeNode(left);
            ClearUpTreeNode(right);
        }
    }
View Code

  (2)功能、特殊輸入測試

    //            10
    //         /      \
    //        5        12
    //       /\        
    //      4  7     
    // 有兩條路徑上的結點和為22
    public static void Test1()
    {
        BinaryTreeNode node10 = new BinaryTreeNode(10);
        BinaryTreeNode node5 = new BinaryTreeNode(5);
        BinaryTreeNode node12 = new BinaryTreeNode(12);
        BinaryTreeNode node4 = new BinaryTreeNode(4);
        BinaryTreeNode node7 = new BinaryTreeNode(7);

        SetSubTreeNode(node10, node5, node12);
        SetSubTreeNode(node5, node4, node7);

        Console.WriteLine("Two paths should be found in Test1.");
        TestPortal("Test1", node10, 22);

        ClearUpTreeNode(node10);
    }

    //            10
    //         /      \
    //        5        12
    //       /\        
    //      4  7     
    // 沒有路徑上的結點和為15
    public static void Test2()
    {
        BinaryTreeNode node10 = new BinaryTreeNode(10);
        BinaryTreeNode node5 = new BinaryTreeNode(5);
        BinaryTreeNode node12 = new BinaryTreeNode(12);
        BinaryTreeNode node4 = new BinaryTreeNode(4);
        BinaryTreeNode node7 = new BinaryTreeNode(7);

        SetSubTreeNode(node10, node5, node12);
        SetSubTreeNode(node5, node4, node7);

        Console.WriteLine("No paths should be found in Test2.");
        TestPortal("Test2", node10, 15);

        ClearUpTreeNode(node10);
    }

    //               5
    //              /
    //             4
    //            /
    //           3
    //          /
    //         2
    //        /
    //       1
    // 有一條路徑上面的結點和為15
    public static void Test3()
    {
        BinaryTreeNode node5 = new BinaryTreeNode(5);
        BinaryTreeNode node4 = new BinaryTreeNode(4);
        BinaryTreeNode node3 = new BinaryTreeNode(3);
        BinaryTreeNode node2 = new BinaryTreeNode(2);
        BinaryTreeNode node1 = new BinaryTreeNode(1);

        node5.leftChild = node4;
        node4.leftChild = node3;
        node3.leftChild = node2;
        node2.leftChild = node1;

        Console.WriteLine("One path should be found in Test3.");
        TestPortal("Test3", node5, 15);

        ClearUpTreeNode(node5);
    }

    // 1
    //  \
    //   2
    //    \
    //     3
    //      \
    //       4
    //        \
    //         5
    // 沒有路徑上面的結點和為16
    public static void Test4()
    {
        BinaryTreeNode node1 = new BinaryTreeNode(1);
        BinaryTreeNode node2 = new BinaryTreeNode(2);
        BinaryTreeNode node3 = new BinaryTreeNode(3);
        BinaryTreeNode node4 = new BinaryTreeNode(4);
        BinaryTreeNode node5 = new BinaryTreeNode(5);

        node1.leftChild = node2;
        node2.leftChild = node3;
        node3.leftChild = node4;
        node4.leftChild = node5;

        Console.WriteLine("No paths should be found in Test4.");
        TestPortal("Test4", node1, 16);

        ClearUpTreeNode(node1);
    }

    // 樹中只有1個結點
    public static void Test5()
    {
        BinaryTreeNode node1 = new BinaryTreeNode(1);

        Console.WriteLine("One paths should be found in Test5.");
        TestPortal("Test5", node1, 1);

        ClearUpTreeNode(node1);
    }

    // 樹中沒有結點
    public static void Test6()
    {
        Console.WriteLine("No paths should be found in Test6.");
        TestPortal("Test6", null, 0);
    }

3.2 測試結果

作者:周旭龍

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連結。

相關推薦

Offer試題23.中和路徑

一、題目:二叉樹中和為某一值的路徑 題目:輸入一棵二叉樹和一個整數,打印出二叉樹中結點值的和為輸入整數的所有路徑。從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。例如輸入下圖中二叉樹和整數22,則打印出兩條路徑,第一條路徑包含結點10、12,第二條路徑包含結點10、5和7。   二叉

offer第24題(中和路徑

題目:輸入一顆二叉樹和一個整數,打印出二叉樹中結點值的和為輸入整數的所有路徑。路徑定義為從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。 思想:由於本題中的根要在前面,因而我們首先想到的是前序遍歷。當用前序遍歷的方式訪問某一節點時,我們把該節點新增到路徑上,並累加

offer-Java版】25中和路徑

二叉樹中值和為某一值的路徑:類似圖的深度優先遍歷 對於此類問題一直有點弱,多想幾次就OK了–主要是不熟悉,畢竟程式碼寫出來之後一看就明白,但是自己想的時候還是有點困難 publi

offer 試題重建

題目:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。 思路:二叉樹先序是根左右,中序 是左根右。所以先找到

offer試題的映象(遞迴、迴圈解法及測試用例)

題目:給定二叉樹,將其變換為源二叉樹的映象。 二叉樹的定義如下: struct TreeNode {     int val;     TreeNode* left;     TreeNode* right; }; 輸入描述: 二叉樹的映象定義:     源二叉樹    

【LeetCode & offer刷題】題934 中和路徑(112. Path Sum)

【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...) 112. Path Sum Given a binary tree and a sum, determine if the tree has a root-to-leaf path suc

offer{試題25中和路徑}

思路:這道題比較有意思,類似的題我在面試裡經常遇到過,圍繞著樹的深度遍歷和廣度遍歷做文章,針對這種型別的題,大家更多考慮的解決方案是遞迴,說白了二叉樹就是一群小二叉樹,上次做寶寶樹的筆試題的時候,出的演算法題就是求任意兩個節點之間的最遠距離,說白了還是遍歷的問題,回到這道題  &n

Offer 試題34中和路徑 Java程式碼實現

題目:輸入一棵二叉樹和整數,打印出二叉樹中節點值得和為輸入整數的所有路徑。從樹的根節點開始往下一直到葉節點所經過的節點形成一條路徑。 解題思路:路徑從根節點開始,應該用類似於前序遍歷的方式訪問樹節點。

offer試題34中和路徑

題目:輸入一顆二叉樹的跟節點和一個整數,打印出二叉樹中結點值的和為輸入整數的所有路徑。路徑定義為從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。(注意: 在返回值的list中,陣列長度大的陣列靠前)  連結:https://www.nowcoder.com/qu

Offer試題25(Java版)中和路徑

題目:輸入一顆二叉樹和一個整數,打印出二叉樹中結點值的和為輸入整數的所有路徑。從樹的根節點開始往下一直到葉結點所經過的所有的結點形成一條路徑。 如下圖,輸入二叉樹和整數22,則打印出兩條路徑,第一條路徑包含結點10,12,第二條路徑包含的結點為10,5,7. 一般的資料結構

Offer試題22.搜尋的後序遍歷序列

一、題目:二叉搜尋樹的後序遍歷序列 題目:輸入一個整數陣列,判斷該陣列是不是某二叉搜尋樹的後序遍歷的結果。如果是則返回true,否則返回false。假設輸入的陣列的任意兩個數字都互不相同。   例如在下面的一顆二叉搜尋樹中,輸入陣列{5,7,6,9,11,10,8},則返回true,因為這個整數序列是

Offer試題25.搜尋與雙向連結串列

一、題目:二叉搜尋樹與雙向連結串列 題目:輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成一個排序的雙向連結串列。要求不能建立任何新的結點,只能調整樹中結點指標的指向。比如輸入下圖中左邊的二叉搜尋樹,則輸出轉換之後的排序雙向連結串列。   二叉搜尋樹的節點定義如下,這裡使用C#語言描述:

Offer系列-試題25中和路徑

題目:輸入一顆二叉樹和一個整數,打印出二叉樹中結點值的和為輸入整數的所有路徑。路徑定義為從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。 思路: 程式碼: vector<vector&

offer——試題25中和路徑

void FindPath(BinaryTreeNode* pRoot, int expectedSum) { if(pRoot == NULL) return;

offer試題25中和路徑

題目:輸入一棵二叉樹和一個整數,打印出二叉樹中結點值的和為輸入整數的所有路徑。從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。思路:用棧記錄路徑,sum記錄當前和。如果是葉結點,判斷sum是否等於target,如果等於則輸出。help的方法最後需要將棧頂彈出,sum

牛客網線上程式設計專題《offer-試題39》的深度

題目連結: 題目描述: 解題思路: 解法:遞迴的遍歷一棵數的左右子樹。 已經AC的程式碼: public class treeDepth39 { public class Tr

offer試題7:重建(java實現)

題目:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建該二叉樹,假設輸入的前序遍歷和中序遍歷的結果都不含重複的數字。例如:輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6}則重建二叉樹:其中二叉樹的定義如下:  * publi

Offer試題6 重建

題目:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入的前序遍歷序列{1,2,4,7,3,5,6,8}和後序遍歷序列{4,7,2,1,5,3,8,6},則重建出如圖所示的二叉樹 二叉樹結點定義如下:

offer試題25 中和路徑

解題思路:首先需要理解路徑的概念:路徑總是從根節點到葉節點,由於路徑是從根節點開始,所以可以考慮用先序遍歷的方式。每遍歷完一個節點進入節點的左子樹時,需要將當前節點儲存起來,作為路徑中的一個節點,之所以需要儲存路徑上的節點,是因為需要計算路徑的和,是否和待查詢元素相同。因此

offer 試題25—中和路徑

題目: 輸入一棵二叉樹和一個整數,打印出二叉樹中節點值的和為輸入整數的所有路徑。從樹的根節點開始往下一直到葉節點所經過的節點形成一條路徑。 基本思想: 規律: 遍歷到某一節點時,將節點新增到路徑中,並累加該節點的值。如果該節點為葉節點並且路徑中節點值的和等於輸入整