二叉树问题总结


记录自己在学习中遇到的二叉树问题所编写代码,以方便复习。

先中后序遍历问题

1.分别按照二叉树先序,中序和后序打印所有的节点;

private int i =0;  //成员变量,方法也可以使用,因此不用再向递归中传递了
    private int j = 0;
    private int k = 0;
    public int[][] threeOrders (TreeNode root) {
        // write code here
        int size = getsize(root);
        if(root == null) return null;
        int[][] result = new int[3][size];
        process(root,result);
        return result;
    }

    public void process(TreeNode root,int[][] result){
        if(root == null) return;
        
        result[0][i++] = root.val; //先序
        process(root.left,result);
        result[1][j++] = root.val;//中序
        process(root.right,result);
        result[2][k++] = root.val;//后序
    }
    public int getsize(TreeNode root){
        if(root == null){
            return 0;
        }
        int size = 1 + getsize(root.left) + getsize(root.right);
        return size;
    }

节点最小公共祖先

//这种方法必须是o1,o2都在树种中,如果不在树中则判断是错误的
	public static Node lowestAncestor(Node head, Node o1, Node o2) {
		if (head == null || head == o1 || head == o2) { // base case
			return head;
		}
		Node left = lowestAncestor(head.left, o1, o2);
		Node right = lowestAncestor(head.right, o1, o2);
		if (left != null && right != null) {
			return head;
		}
		// 左右两棵树,并不都有返回值
		return left != null ? left : right;
	}

//把结点和其父存到map里,然后把其中一个节点的祖先全部存到set中去
//再在set中找另一个结点的祖先,最先找到的祖先为最小公共祖先
public static class Record1 {
		private HashMap<Node, Node> map;

		public Record1(Node head) {
			map = new HashMap<Node, Node>();
			if (head != null) {
				map.put(head, null);
			}
			setMap(head);
		}

		private void setMap(Node head) {
			if (head == null) {
				return;
			}
			if (head.left != null) {
				map.put(head.left, head);
			}
			if (head.right != null) {
				map.put(head.right, head);
			}
			setMap(head.left);
			setMap(head.right);
		}

		public Node query(Node o1, Node o2) {
			HashSet<Node> path = new HashSet<Node>();
			while (map.containsKey(o1)) {
				path.add(o1);
				o1 = map.get(o1);
			}
			while (!path.contains(o2)) {
				o2 = map.get(o2);
			}
			return o2;
		}
	}

//递归方式,判断每一种可能性
//如果不存在祖先返回null
public class Solution {
    public class Returned{
    TreeNode common;
    boolean haso1;
    boolean haso2;
    public Returned(TreeNode common, boolean haso1,boolean haso2){
        this.common = common; 
        this.haso1 = haso1;
        this.haso2 = haso2;
    }
}
    public int lowestCommonAncestor (TreeNode root, int o1, int o2) {
        // write code here
        if(root==null) return Integer.MIN_VALUE;
        Returned result = process(root,o1,o2);
        if(result.common == null) return Integer.MIN_VALUE;
        return result.common.val;
    }
    public Returned process(TreeNode root,int o1, int o2){
        if(root==null) return new Returned(null,false,false);
        Returned L = process(root.left,o1,o2);
        Returned R = process(root.right,o1,o2);
        //存在最低公共祖先
            //最低公共祖先在子树上
        if(L.common != null) {
            return new Returned(L.common,true,true);
        }
        if(R.common != null) {
            return new Returned(R.common,true,true);
        }
            //在自己这个结点上,左右子树各有一个节点
        if((L.haso1&&R.haso2) || (L.haso2 && R.haso1)){
            return new Returned(root,true,true);
        }
            //在自己这个结点上,左右子树有其中一个节点,另一个为自己
        boolean b1 = (L.haso1 || R.haso1)&& root.val == o2;
        boolean b2 = (L.haso2 || R.haso2)&& root.val == o1;
        if(b1 || b2){
            return new Returned(root,true,true);
        }
        //不存在最低公共祖先
            //只有o1
        b1 = ((L.haso1 && !R.haso2 && root.val != o2) ||
              (R.haso1 && !L.haso2 && root.val != o2) || 
              (root.val == o1 && !(L.haso2 || R.haso2)) );
        if(b1) return new Returned(null,true,false);
            //只有o2
        b2 = ((L.haso2 && !R.haso1 && root.val != o1) ||
              (R.haso2 && !L.haso1 && root.val != o1) || 
              (root.val == o2 && !(L.haso1 || R.haso1)) );
        if(b2) return new Returned(null,false,true);
        return new Returned(null,false,false);
    }
}

BFS

如果不需要确定当前遍历到了哪一层,模板如下:

void bfs() {
    vis[] = 0;
    queue<int> pq(start_val);
 
    while (!pq.empty()) {
        int cur = pq.front(); pq.pop();
        for (遍历cur所有的相邻节点nex) {
            if (nex节点有效 && vis[nex]==0){
                vis[nex] = 1;
                pq.push(nex)
            }
        }
    }
}

如果需要确定遍历到哪一层,模板如下:

void bfs() {
    int level = 0;
    vis[] = 0; // or set
    queue<int> pq(original_val);
    while (!pq.empty()) {
        int sz = pq.size();
 
        while (sz--) {
                int cur = pq.front(); pq.pop();
            for (遍历cur所有的相邻节点nex) {
                if (nex节点有效 && vis[nex] == 0) {
                    vis[nex] = 1;
                    pq.push(nex)
                }
            } // end for
        } // end inner while
        level++;
 
    } // end outer while
}

对称二叉树

设置一个递归函数isSame(r1, r2),表示如果对称,返回true,否则返回false
递归终止条件:r1== nullptr && r2== nulllptr, 直接返回true,否则,如果只有一个为nullptr,返回false
下一步递归:如果r1->val == r2->val, 则isSame(root1->left, root2->right) && isSame(root1->right, root2->left);

如果先镜像出一个mirror,再去递归判断是否相同,是不对的;镜像以后,原始树的结构应该也改了,所以是不对的
class Solution {
public:
    bool isSame(TreeNode *root1, TreeNode *root2) {
        if (!root1 && !root2) return true;
        if (!root1 || !root2) return false;
        return root1->val == root2->val &&
        isSame(root1->left, root2->right) &&
        isSame(root1->right, root2->left);
    }
    bool isSymmetrical(TreeNode* pRoot)
    {
        return isSame(pRoot, pRoot);
    }
 
};
	//定义和先序遍历对称的方式进行遍历 中左右->中右左
    //同时把null算进去
    boolean isSymmetrical(TreeNode root) {
        if(root == null) return true;
        return process(root,root);
    }
    public boolean process(TreeNode left,TreeNode right){
        boolean result = false;
        if(left == null && right == null){
            result = true;
        }
        if(left!=null && right!=null){
            if(left.val == right.val){
                result = true;
            }
            if(result){
                result = process(left.left,right.right);
            }
            if(result){
                result = process(left.right,right.left);
            }
        }
        return result;     
    }
	

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值