二叉树(三)

求二叉树中两个节点的最近公共祖先节点

思路1:

  1. 如果两个节点在左右子树,最近的就是他们的根结点
  2. 两个节点在同一侧,用子问题方法求解
BTreeNode * Find(BTreeNode *root, TDataType data)
{
    if(root == NULL)
    {
        return NULL;
    }
    if(root->data == data)
    {
        return root;
    }
    
	BTreeNode *result = Find(root->left, data);
	if (result != NULL) 
	{
		return result;
	}

	result = Find(root->right, data);
	if (result != NULL) 
	{
		return result;
	}
	else 
	{
		return NULL;
	}
}

BTreeNode * GetAncestor(BTreeNode *root, BTreeNode *node1, BTreeNode *node2)
{
    BTreeNode *node1InLeft = Find(root->left, node1->data);
	BTreeNode *node2InLeft = Find(root->left, node2->data);
	BTreeNode *node1InRight = Find(root->right, node1->data);
	BTreeNode *node2InRight = Find(root->right, node2->data);
	
	if((node1InLeft && node2InLeft) || (node1InRight && node2InRight))
	{
	    return root;
	}
	
	if (node1InLeft) {
		return GetAncestor(root->left, node1, node2);
	}
	else {
		return GetAncestor(root->right, node1, node2);
	}
}

思路2:(这里我用C++写出,题目源自leetcode:236)

  1. 通过非递归的后序遍历,找到从根到结点的路径保存在栈里
  2. 用类似链表交叉求交点的思路,找到最近的公共祖先
/**
 * Definition for a binary tree node.
 * struct BTreeNode {
 *     int val;
 *     BTreeNode *left;
 *     BTreeNode *right;
 *     BTreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    
    bool getAncestor(BTreeNode* root, BTreeNode* p, stack<BTreeNode*>& sta){
        if(root == NULL){
            return false;
        }
        if(root == p){
            sta.push(root);
            return true;
        }
        if(getAncestor(root->left,p,sta)||getAncestor(root->right,p,sta)){
            sta.push(root);
            return true;
        }
        return false;
    }
    
    TreeNode* lowestCommonAncestor(BTreeNode* root, BTreeNode* p, BTreeNode* q) {
        stack<BTreeNode*> pstack,qstack;
        getAncestor(root,p,pstack);
        getAncestor(root,q,qstack);
        BTreeNode* top = NULL;
        
        while(!pstack.empty() && !qstack.empty() && qstack.top() == pstack.top()){
            top = qstack.top();
            pstack.pop();
            qstack.pop();
        }
        return top;
    }
};

判断一颗二叉树是否是平衡二叉树

思路:

  1. 左子树是否平衡&&右子树是否平衡
  2. 高度差不能超过1
  3. 空树/只有一个节点的树 是平衡树
#define MAX(a, b)	((a) > (b) ? (a) : (b))
int GetHeight(BTreeNode* root)
{
	if (root == NULL) {
		return 0;
	}

	return MAX(GetHeight(root->left), GetHeight(root->right)) + 1;
}

bool IsBalanceTree(BTreeNode* root)
{
    if(root == NULL)
    {
        return true;
    }
    //左子树是否平衡
    if(!(IsBalanceTree(root->left)))
    {
        return false;
    }
    //右子树是否平衡
    if(!(IsBalanceTree(root->right)))
    {
        return false;
    }
    //计算高度
    int leftHeight = GetHeight(root->left);
    int rightHeight = GetHeight(root->right);
    int heigth = leftHeight - rightHeight;
    if(height >= -1 && height <= 1)
    {
        return true;
    }
     return false;
}
  • 进阶版(省掉求高度的函数)
#define MAX(a, b)	((a) > (b) ? (a) : (b))
bool IsBalanceAd(BTreeNode *root, int *pHeight)
{
    if(root == NULL)
    {
        *pHeight = 0;
        return true;
    }
    int leftHeight;
	if (!(IsBalanceAd(root->left, &leftHeight))) {
		// 左子树不平衡,没必要继续,整棵树一定不平衡
		*pHeight = -1;	// 不平衡的情况,高度没有用,给的值无意义
		return false;
	}

	// 判断右子树是否平衡
	int rightHeight;
	if (!(IsBalanceAd(root->right, &rightHeight))) {
		// 右子树不平衡,没必要继续,整棵树一定不平衡
		*pHeight = -1;	// 不平衡的情况,高度没有用,给的值无意义
		return false;
	}

	// 真正的整棵树的高度
	*pHeight = MAX(leftHeight, rightHeight) + 1;

	// 高度差不超过 1
	int height = leftHeight - rightHeight;
	if (height >= -1 && height <= 1) {
		return true;
	}
	return false;
}

求二叉树中最远的两个节点的距离

思路:

  1. 左子树最远距离
  2. 右子树最远距离
  3. 经过根的最远距离 = 左子树高度 + 右子树高度
#define MAX(a, b)	((a) > (b) ? (a) : (b))
int GetLongDistance(BTreeNode* root, int* maxLeft, int* maxRight)
{
    if(root == NULL)
    {
        maxLeft = 0;
        maxRight = 0;
        return 0;
    }
    int maxLoL,maxLoR,maxRoL,maxRoR;//左子树:向左最大,向右最大;右子树:向左最大,向右最大
    int leftLD,rightLD;
    if(root->left != NULL)
    {
        leftLD = GetLongDistance(root->left, &maxLoL, &maxLoR);
        maxLeft = MAX(maxLoL, maxLoR) + 1;
    }
    else
    {
        leftLD = 0;
        maxLeft = 0
    }
    if(root->right != NULL)
    {
        rightLD = GetLongDistance(root->right, &maxRoL, &maxRoR);
        maxRight = MAX(maxRoL, maxRoR) + 1;
    }
    else
    {
        rightLD = 0;
        maxRight = 0
    }
    
    return MAX(MAX(leftLD,rightLD) , maxLeft + maxRight);
}

有前序遍历和中序遍历重建二叉树(前序遍历结果:1,2,3,4,5,6 中序遍历结果:4,2,5,1,6,3)

思路:

  1. 从前序取根的值:第一个元素总是树的根节点的值
  2. 中序遍历序列中,找到根节点的下标:左子树的节点的值位于根节点的值的左边,右子树的节点的值位于根节点的值的右边。
  3. 递归建立二叉树
typedef struct BTreeNode {
	int data;
	struct BTreeNode *left;
	struct BTreeNode *right;
}	BTreeNode;

BTreeNode * CreateNode(int data)
{
	BTreeNode *node = (BTreeNode *)malloc(sizeof(BTreeNode));
	assert(node);
	node->data = data;
	node->left = node->right = NULL;

	return node;
}

BTreeNode * CreateTree(int* preOrder, int* inOrder, int size)
{
    if(size <= 0)
    {
        return NULL;
    }
    // 从前序取根的值
	int rootValue = preOrder[0];
	// 从中序中找到根的下标
	int rootIndexInOrder = -1;
	for (int i = 0; i < size; i++) {
		if (inOrder[i] == rootValue) {
			rootIndexInOrder = i;
		}
	}
	assert(rootIndexInOrder != -1);
	// rootIndexInOrder 既是根在中序中的下标,也是左子树结点的个数
	BTreeNode* newRoot = CreateNode(rootValue);
	newRoot->left = CreateTree(preOrder+1, inOrder, rootIndexInOrder);
	newRoot->right = CreateTree(preOrder+1+rootIndexInOrder, inOrder + 1 + rootIndexInOrder, size-rootIndexInOrder-1);
	
	return root;
}

猜你喜欢

转载自blog.csdn.net/qq_40355351/article/details/84674622
今日推荐