题干:
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针,即node.next的最终所指一定是二叉树的根节点。
思路:
思路1:
首先中序遍历这个二叉树,然后把节点按照顺序放入到list内部,然后再根据传入的node进入到list中找下一个节点即可。
思路2:
直接一边中序遍历,一边找这个值,那么时间复杂度为O(N),空间复杂度可以降到O(1),主要的方法就是分情况进行讨论即可。具体的规律可以总结如下:
仔细观察,可以把中序下一结点归为几种类型:
- 有右子树,下一结点是右子树中的最左结点,例如 B,下一结点是 H
- 无右子树,且结点是该结点父结点的左子树,则下一结点是该结点的父结点,例如 H,下一结点是 E
- 无右子树,且结点是该结点父结点的右子树,则我们一直沿着父结点追朔,直到找到某个结点是其父结点的左子树,如果存在这样的结点,那么这个结点的父结点就是我们要找的下一结点。例如 I,下一结点是 A;例如 G,并没有符合情况的结点,所以 G 没有下一结点
具体代码如下:
解法1:
public class item58 {
static ArrayList<TreeLinkNode> list = new ArrayList<>();
public TreeLinkNode GetNext(TreeLinkNode pNode)
{
TreeLinkNode node = pNode;
while (pNode.next!=null){
pNode=pNode.next;
}
inorder(pNode);
for(int i=0;i<list.size()-1;i++){
if(list.get(i)==node){
return list.get(i+1);
}
}
return null;
}
public void inorder(TreeLinkNode node){//递归实现中序遍历,放入list
if(node!=null){
inorder(node.left);
list.add(node);
inorder(node.right);
}
}
}
解法2:
public class Solution {
2.
3. public TreeLinkNode GetNext(TreeLinkNode pNode) {
4. // 1.
5. if (pNode.right != null) {//有右子树,下一结点是右子树中的最左结点
6. TreeLinkNode pRight = pNode.right;
7. while (pRight.left != null) {
8. pRight = pRight.left;
9. }
10. return pRight;
11. }
12. // 2.
13. if (pNode.next != null && pNode.next.left == pNode) {//无右子树,且结点是该结点父结点的左子树,则下一结点是该结点的父结点
14. return pNode.next;
15. }
16. // 3.
17. if (pNode.next != null) {//无右子树,且结点是该结点父结点的右子树,则我们一直沿着父结点追朔,直到找到某个结点是其父结点的左子树,如果存在这样的结点,那么这个结点的父结点就是我们要找的下一结点。
18. TreeLinkNode pNext = pNode.next;
19. while (pNext.next != null && pNext.next.right == pNext) {
20. pNext = pNext.next;
21. }
22. return pNext.next;
23. }
24. return null;
25. }
26. }