Data structure---Supplement to basic interview questions

1. LeetCode Problem 110-Balanced Binary Tree

Link: link .
Insert picture description here
The absolute value of the height difference between the left and right subtrees of each node of a binary tree does not exceed 1 is an important point for understanding this question.
There are two ways of solving this problem ①It is equivalent to the idea of ​​preorder traversal. Divide it into the current tree, the left subtree and the right subtree, write out the current tree ideas, and then implement recursion on the left subtree and the right subtree. If the left subtree and right subtree of the current tree do not meet the conditions of a balanced binary tree, then you can directly return false, and then start to judge whether each subtree in the left subtree meets the definition of a balanced binary tree. In short, every knot Points are regarded as a root node of a binary tree to judge whether it meets the definition of a balanced binary tree.

int TreeDepth(struct TreeNode* root)
{
    
    
    if(root == NULL)
        return 0;
    //为的就是消除代码冗余
    int leftDepth = TreeDepth(root->left);
    int rightDepth = TreeDepth(root->right);

//求出左右子树较大的哪一个
    return leftDepth > rightDepth? leftDepth+1 :rightDepth+1;

}

bool isBalanced(struct TreeNode* root){
    
    
    if(root == NULL)
       return true;
    //这样重新定义一个变量的目的就是消除代码的冗长
    int gap = TreeDepth(root->left)-TreeDepth(root->right);
    if(abs(gap) > 1)
        return false;

    return isBalanced(root->left) && isBalanced(root->right);
}

But you will find that the time complexity of such a self-balanced binary tree is between O(N)~O(N*N) , as long as the traversal time complexity is O(N), when you come in and traverse the left and right subtrees, they will not Satisfy the situation of the balanced binary tree, but when you have been traversing until the last subtree of the right subtree does not meet the definition of the balanced binary tree, basically the calculation of time complexity satisfies an arithmetic sequence, which is almost O(N*N) , **So can it be optimized? **You will find this idea of ​​preorder traversal, there will be a lot of repeated calculation of the height of the tree. So using subsequent traversal here is more optimized. You will judge the left tree when you come in, calculate the height of the last left subtree in the left tree and return true or false. In the same process of calculating the right tree, then you will find each of yours in the end The height of a tree considered by the node is calculated only once, without repeated calculations.

//一定要记住在你返回true的同时要返回一个高度值
bool _isBalanced(struct TreeNode* root,int* pDepth)
{
    
    
    //此时需要的是相当于后续遍历
    //先找到你最左边的树,再试最右边的树,在满足的同时返回true
    if(root == NULL)
    {
    
    
        *pDepth = 0;
        return true;
    }
    else
    {
    
    
        int leftDepth = 0;
        if(_isBalanced(root->left,&leftDepth) == false)
            return false;

        int rightDepth = 0;
        if(_isBalanced(root->right,&rightDepth) == false)
            return false;
        //走到这里说明左树和右树中所有的结点所对应小子树都是满足平衡二叉树的条件
        if(abs(leftDepth-rightDepth) > 1)
            return false;
        
        *pDepth = leftDepth > rightDepth?leftDepth+1:rightDepth+1;
        return true;
    }
}
bool isBalanced(struct TreeNode* root){
    
    
    int depth = 0;
    return  _isBalanced(root,&depth);
}

2. Niuke.com—Binary Tree Traversal

Link: link .
Insert picture description here
According to the pre-order traversal and the input is abc##de#g##f##, a binary tree can be drawn.
Insert picture description here

#include<stdio.h>
#include<stdlib.h>

typedef struct TreeNode {
    
    
     char val;
     struct TreeNode *left;
     struct TreeNode *right;
 }TreeNode;

TreeNode* CreateTree(char* str,int* pi)
{
    
    
    if(str[*pi] == '#')
    {
    
    
        (*pi)++;
        return NULL;
    }
    else
    {
    
    
        TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
        root->val = str[*pi];
        //构建左右子树
        (*pi)++;
        root->left = CreateTree(str,pi);
        root->right = CreateTree(str,pi);
        
        return root;
    }
}

void InOrder(TreeNode* root)
{
    
    
    if(root == NULL)
        return;
    InOrder(root->left);
    printf("%c ",root->val);
    InOrder(root->right);
}

int main()
{
    
    
    char str[100];
    scanf("%s ",str);
    
    int i = 0;
    TreeNode* root = CreateTree(str, &i);
    InOrder(root);
    return 0;
}

Like LeetCode, Niuke.com needs to include header files and other content by itself. Since drawing disks are not very useful, they can only use screenshots to roughly analyze this recursive process. The following figure is an analysis of the process of building the left tree.
Insert picture description here

3. Realization of the sequence

The realization of the sequence needs to rely on the nature of the queue, first in, first out.
Insert picture description here
Here also need to use the original Queue.h and Queue.c files, which are omitted here, but you need to add the BTNode* file declaration in your Queue.h

Queue.h
//相当于把你的struct BinaryTreeNode拿过来申明一下
extern struct BinaryTreeNode;
typedef struct BinaryTreeNode*  QDateType;
//这里可以把BTNode的定义放到这里,但是这是一个Queue的头文件,有点挫


//二叉树的层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
    
    
	//在这里所定义的队列里面放的可不能只是值,那么你就在他出的时候找不到他的左右孩子入队列了
	Queue q;
	QueueInit(&q);
	if (root == NULL)
		return;
	QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
    
    
		BTNode* front = QueueFront(&q);
		//这里的Pop只是把这个数据从队列里面拿出来了,并没有删除
		QueuePop(&q);//从这个队列里面把这个结点拿出来
		printf("%c ", front->_date);
		if (front->_left)
		{
    
    
			QueuePush(&q, front->_left);
		}
		if (front->_right)
		{
    
    
			QueuePush(&q, front->_right);
		}
	}
	QueueDestory(&q);
	printf("\n");
}

3.1 Is it a complete binary tree

With the help of the above thoughts, the difference between a complete binary tree and an incomplete binary tree is:
in the layer sequence traversal,
if you are a complete binary tree, then your nodes are all gathered in the front (the node and your NULL are clearly separated )
But if you are a non-complete binary tree, you will find that your node may contain NULL

//判断二叉树是否是一颗完全二叉树
//这个题借助上面的思想,完全二叉树和非完全二叉树的区别就是:
//在层序遍历中   
//如果你是完全二叉树那么你的结点都是聚集在前面的(结点和你的NULL是明显分割开的),
//但是如果你是非完全二叉树你会发现,你的结点中间可能包含了NULL
int BinaryTreeComplete(BTNode* root)
{
    
    
	Queue q;
	QueueInit(&q);
	if (root == NULL)
		return 1;  //是就返回1,不是返回0
	QueuePush(&q, root);

	//如果是完全二叉树,那么你的结点都出队列之后,队列就是NULL的
	//如果是非完全二叉树,当你遇见一个break之后,你去检查队列,你会发现队列是不为NULL的
	while (!QueueEmpty(&q))
	{
    
    
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front == NULL)
			break;


		QueuePush(&q, front->_left);
		QueuePush(&q, front->_right);
	}
	//此时上面已经遇见了一个空,再来判断队列里面剩下的
	while (!QueueEmpty(&q))
	{
    
    
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front)
		{
    
    
			QueueDestory(&q);
			return 0;
		}
	}
	//一定要记住放置内存泄漏,要对其所创建的队列进行释放
	QueueDestory(&q);
	return 1;
}

Insert picture description here

Guess you like

Origin blog.csdn.net/MEANSWER/article/details/112788445