Suplemento de perguntas básicas da entrevista
1. Problema LeetCode 110-árvore binária balanceada
Link: ligação .
O valor absoluto da diferença de altura entre as subárvores esquerda e direita de cada nó de uma árvore binária não exceda 1 é um ponto importante para entender esta questão.
Existem duas maneiras de resolver esse problema ① É equivalente à ideia de travessia de pré-ordem. Divida-a na árvore atual, a subárvore esquerda e a subárvore direita, escreva as idéias da árvore atual e, a seguir, implemente a recursão na subárvore esquerda e na subárvore direita. Se as subárvores esquerda e direita da árvore atual não atender as condições de uma árvore binária equilibrada, então você pode voltar diretamente falsa, e então começar a julgar se cada sub-árvore na subárvore esquerda satisfaz a definição de uma árvore binária equilibrada. Em Resumindo, cada nó Pontos são considerados como um nó raiz de uma árvore binária para julgar se ele atende à definição de uma árvore binária balanceada.
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);
}
Mas você vai descobrir que a complexidade de tempo de tal árvore binária auto-balanceada está entre O (N) ~ O (N * N) , desde que a complexidade de tempo de percurso seja O (N), quando você entra e atravessa o subárvores esquerda e direita, eles não satisfarão a situação da árvore binária balanceada, mas quando você tiver percorrido até a última subárvore da subárvore direita não atenda à definição da árvore binária balanceada, basicamente o cálculo da complexidade de tempo satisfaz um sequência aritmética, que é quase O (N * N), ** Então, pode ser otimizada? ** Você encontrará essa ideia de travessia de pré-ordem, haverá muitos cálculos repetidos da altura da árvore. Portanto, usar a travessia subsequente aqui é mais otimizado. Você julgará a árvore esquerda ao entrar, calculará a altura da última subárvore esquerda na árvore esquerda e retornará verdadeiro ou falso. No mesmo processo de cálculo da árvore direita, você irá encontrar cada um de seus A altura de uma árvore considerada pelo nó é calculada apenas uma vez, sem cálculos repetidos.
//一定要记住在你返回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 .
De acordo com a passagem de pré-pedido e a entrada é abc ## de # g ## f ##, uma árvore binária pode ser desenhada.
#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;
}
Como o LeetCode, o Niuke.com precisa incluir arquivos de cabeçalho e outros conteúdos por si só. Como os discos de desenho não são muito úteis, eles só podem usar capturas de tela para analisar de maneira aproximada esse processo recursivo. A figura a seguir é uma análise do processo de construção da árvore esquerda.
3. Realização da sequência
A realização da sequência precisa depender da natureza da fila, primeiro a entrar, primeiro a sair.
Aqui, você também precisa usar os arquivos Queue.he Queue.c originais, que são omitidos aqui, mas você precisa adicionar a declaração de arquivo BTNode * em seu 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 É uma árvore binária completa
Com a ajuda dos pensamentos acima, a diferença entre uma árvore binária completa e uma árvore binária incompleta é:
na travessia da sequência de camadas,
se você for uma árvore binária completa, então seus nós estão todos reunidos na frente (o nó e seu NULL são claramente separados)
Mas se você for uma árvore binária não completa, você verá que seu nó pode conter 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;
}