私の友人は私にこの質問をしました
最初のタイトルは次のとおりでした: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
彼が言及したインターネット上のJavaコード:
/**
* 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;
}
}
次に、Pythonコードを書き直します。
# 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のスライスは元のリストへの参照を返すため、画像の場合、図に示すようにパラメーターが渡されると、2つのリストは実際の呼び出し中に再帰によって変更されているため、例外はスローされません。 。Javaについても同じことが言えます。同じ原則がサブリストのサブリストにも当てはまります。サブリストによって生成されるサブリストは、元のリストのビューにすぎません(参照: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