记录自己在学习中遇到的二叉树问题所编写代码,以方便复习。
先中后序遍历问题
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;
}