제 친구가이 질문을했습니다
처음에 제목은 https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/ 였습니다.
바이너리 트리의 선주문 순회 및 중간 순회 결과를 입력하고 바이너리 트리를 다시 빌드하십시오. 선주문 순회 및 중순 순회 입력 결과에 반복되는 숫자가 포함되지 않는다고 가정합니다.
예를 들어, 주어진
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
다음 이진 트리를 반환합니다.
3
/ \
9 20
/ \
15 7
그가 언급 한 인터넷상의 자바 코드 :
/**
* 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;
}
}
그런 다음 파이썬 코드를 다시 작성하십시오.
# 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
위의 코드는 모두 LeetCode 실행을 통과하고 정답이 주어졌고 로컬에서 실행해도 괜찮 았습니다.
언뜻보기에는 실제로 문제가 없지만 신중하게 디버깅하면 문제가 있음을 알 수 있습니다.
디버그 코드 :
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))
운영
이 문제는 오랫동안 나를 괴롭 혔습니다.
나중에 큰 남자의 지시에 따라
copy.deepcopy로 코드를 변경할 때 언급 된 문제를 발견하면 예외가 발생합니다.
python3의 조각은 원본 목록에 대한 참조를 반환하기 때문에 그림의 경우 그림과 같이 매개 변수가 전달되면 실제 호출 중에 두 목록이 재귀로 수정되어 예외가 발생하지 않습니다. . 자바도 마찬가지입니다. 하위 목록의 하위 목록에도 동일한 원칙이 적용됩니다. 하위 목록에서 생성 된 하위 목록은 원래 목록의보기 일뿐입니다 (참조 : https://blog.csdn.net/u013254237/article/ 세부 정보 / 77504357 )
올바른 솔루션 :
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
또는 원래 어레이에서 작동하지 마십시오.
/**
* 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