Record a pit reference and copy

My friend asked me this question

At first this topic was: https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/

Enter the results of pre-order traversal and mid-order traversal of a binary tree, and please rebuild the binary tree. Assume that the input result of pre-order traversal and middle-order traversal does not contain repeated numbers.

 

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

The java code on the Internet he referred to:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
    //把前序遍历的值和中序遍历的值放到list中
    List<Integer> preorderList = new ArrayList<>();
    List<Integer> inorderList = new ArrayList<>();
    for (int i = 0; i < preorder.length; i++) {
        preorderList.add(preorder[i]);
        inorderList.add(inorder[i]);
    }
    return helper(preorderList, inorderList);
}

private TreeNode helper(List<Integer> preorderList, List<Integer> inorderList) {
    if (inorderList.size() == 0)
        return null;
    //前序遍历的第一个值就是根节点
    int rootVal = preorderList.remove(0);
    //创建跟结点
    TreeNode root = new TreeNode(rootVal);
    //查看根节点在中序遍历中的位置,然后再把中序遍历的数组劈两半,前面部分是
    //根节点左子树的所有值,后面部分是根节点右子树的所有值
    int mid = inorderList.indexOf(rootVal);
    //[0,mid)是左子树的所有值,inorderList.subList(0, mid)表示截取inorderList
    //的值,截取的范围是[0,mid),包含0不包含mid。
    root.left = helper(preorderList, inorderList.subList(0, mid));
    //[mid+1,inorderList.size())是右子树的所有值,
    // inorderList.subList(mid + 1, inorderList.size())表示截取inorderList
    //的值,截取的范围是[mid+1,inorderList.size()),包含mid+1不包含inorderList.size()。
    root.right = helper(preorderList, inorderList.subList(mid + 1, inorderList.size()));
    return root;
}
}

Then rewrite the python code:

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


class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) :
        #print('*',preorder,inorder,end=" ")
        if len(inorder) == 0:return None
        rootval = preorder[0]
        root = TreeNode(rootval)
        index = inorder.index(rootval)
        preorder.remove(rootval)
        root.left=self.buildTree(preorder,inorder[:index])
        root.right=self.buildTree(preorder,inorder[index+1:])
        return root

Both of the above codes passed in LeetCode, and the correct answer was given. They were okay when running locally.

At first glance, there is actually no problem, but careful debugging will find that there is a problem:

Debug code:

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


class Solution:
    def buildTree(self, preorder , inorder) :
        print('(1)',preorder,end="\t ")
        print('(2)',inorder,end=" \t")
        if len(inorder) == 0:return None
        rootval = preorder[0]

        partion = inorder.index(rootval)
        print(partion)
        preorder.remove(rootval)
        print("\t"*25,end=' ')
        print('#3#',preorder, inorder[:partion],end=" \t")
        print('#4#',preorder, inorder[partion+1:])
        root = TreeNode(rootval)
        root.left = self.buildTree(preorder, inorder[:partion])
        root.right = self.buildTree(preorder, inorder[partion + 1:])

        # root.left = self.buildTree(copy.deepcopy(preorder), inorder[:partion])
        # root.right = self.buildTree(copy.deepcopy(preorder), inorder[partion+1:])
        return root

    def PrintFromTopToBottom(self, root):
        # write code here
        outList = []
        queue = [root]
        while queue != [] :
            outList.append(queue[0].val)
            if queue[0].left != None:
                queue.append(queue[0].left)

            if queue[0].right != None:
                queue.append(queue[0].right)

            queue.pop(0)
        return outList

a=Solution()
s1=[3,9,20,15,7]
s2=[9,3,15,20,7]
out=a.buildTree(s1,s2)
print("result:")
print(a.PrintFromTopToBottom(out))

run

 

111111112222222.png

This problem has bothered me for a long time

Later, under the prompt of a big guy

If you find the problem cited when you change the code to copy.deepcopy, an exception will be thrown

Because the slice of python3 returns a reference to the original list, in the case of the picture, when the parameters are passed in as shown in the figure, the two lists have been modified by recursion during the actual call, so no exception is thrown, the same is true for java The same principle applies to the sublist of the sublist. The sublist generated by the sublist is just a view of the original list (reference: https://blog.csdn.net/u013254237/article/details/77504357 )

 

 

Correct solution:

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        if len(preorder)  == 0 :return 
        self.dict = {}
        for i in range(len(inorder)):
            self.dict [inorder[i]] = i
        return self.rebuilt(preorder,0,len(preorder)-1,inorder,0,len(inorder)-1)

    def rebuilt(self,preorder,preStart,preEnd,inorder,inStart,inEnd):
        if preStart>preEnd:
            return
        rootval = preorder[preStart]
        root = TreeNode(rootval)
        if preStart == preEnd :
            return root

        index = self.dict[rootval]
        leftNodeLen= index - inStart
        rightNodeLen = inEnd - index

        root.left = self.rebuilt(preorder,preStart+1,preStart+leftNodeLen,inorder,inStart,index-1)
        root.right = self.rebuilt(preorder,preEnd-rightNodeLen+1,preEnd,inorder,index+1,inEnd)
        return root

Or do not operate on the original array:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
   	public TreeNode buildTree(int[] preorder, int[] inorder) {
	    //把前序遍历的值和中序遍历的值放到list中
	    List<Integer> preorderList = new ArrayList<>();
	    List<Integer> inorderList = new ArrayList<>();
	    for (int i = 0; i < preorder.length; i++) {
	        preorderList.add(preorder[i]);
	        inorderList.add(inorder[i]);
	    }
	    return helper2(preorderList, inorderList);
	}
	
	private TreeNode helper2(List<Integer> preorderList, List<Integer> inorderList) {
	    if (preorderList.size() == 0)
	        return null;
	    int rootVal = preorderList.get(0);
	    TreeNode root = new TreeNode(rootVal);
	    int mid = inorderList.indexOf(rootVal);
	    root.left = helper2(preorderList.subList(1, mid+1), inorderList.subList(0, mid));
	    root.right = helper2(preorderList.subList(mid+1, preorderList.size()),inorderList.subList(mid+1, inorderList.size()));
	    return root;
	}

    
}
class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        if len(preorder) == 0:
            return None
        head = TreeNode(preorder[0])
        tmp1 = inorder.index(preorder[0])
        head.left = self.buildTree(preorder[1:tmp1+1], inorder[0:tmp1])
        head.right = self.buildTree(preorder[tmp1+1:], inorder[tmp1+1:])
        return head

 

Guess you like

Origin blog.csdn.net/yu1336199790/article/details/108805539