Não olhe para o meu leopardo! olhar para baixo! ! !
contente
Primeiro, a operação básica da árvore binária
1. Obtenha o número de nós na árvore
2. Obtenha o número de nós folha
3. Ideia do subproblema - encontre o número de nós folha
4. Obtenha o número de nós na camada Kth
5. Obtenha a altura da árvore binária
6. Verifique se o elemento cujo valor é valor existe
7. Determine se uma árvore é uma árvore binária completa
Duas perguntas sobre oj relacionadas à árvore binária
1. Verifique se duas árvores são iguais
2. Uma subárvore de outra árvore
3. Profundidade máxima da árvore binária
4. Determine se uma árvore binária é uma árvore binária balanceada
6. Construção e travessia da árvore binária
7. Percurso hierárquico da árvore binária
9. Converta a árvore de busca de árvore binária em uma lista duplamente ligada ordenada
12. Árvore binária para criar string
13. Implementação não recursiva de pré-ordem de árvore binária
14. Implementação transversal não recursiva em ordem de árvore binária
Primeiro, a operação básica da árvore binária
1. Obtenha o número de nós na árvore
Duas formas de pensar:
① Percorrendo a ideia:
Defina uma contagem de contador, percorra a árvore binária, conte++ se houver nós; (o método de travessia aqui pode ser qualquer travessia pré-meio-pós-ordem escrita no blog no capítulo anterior)
O código é o seguinte: ! ! ! Observe que a contagem precisa ser definida fora desta função, caso contrário, seu valor de contagem retornará ao inicializador ao recuar
int count=0;
//以遍历的思路写
int size1(BTNode root){
if(root==null) {
return 0;
}else{
count++;
size1(root.left);
size1(root.right);
}
return count;
}
②Ideias de subquestões:
código mostrar como abaixo:
//以子问题思路写 int size(BTNode root){ if(root==null){ return 0; } return size(root.left)+size(root.right)+1; }
2. Obtenha o número de nós folha
Duas formas de pensar:
① Implementação transversal:
Código:
//以遍历的方式访问 int count1=0; int getLeafNodeCount(BTNode root){ // int count1=0; if(root==null){ return 0; }else if(root.left==null && root.right==null){ count1++; } getLeafNodeCount(root.left); getLeafNodeCount(root.right); return count1; }
②Ideias de subquestões:
código mostrar como abaixo:
int getLeafNodeCount(BTNode root){ if(root==null){ return 0; }else if(root.left==null && root.right==null){ return 1; } return getLeafNodeCount(root.left)+getLeafNodeCount(root.right); } }
3. Ideia do subproblema - encontre o número de nós folha
Esta questão foi obtida na segunda ideia em 2
4. Obtenha o número de nós na camada Kth
Ideias para resolução de problemas:
código mostrar como abaixo:
//求第K层结点的个数 public int getKLevelNodeCount(int k){ return getKLevelNodeCount(root, k); } // 获取第K层结点的个数 private int getKLevelNodeCount(BTNode root,int k){ if(root==null || k<=0){ return 0; } if(k==1){ return 1; } return getKLevelNodeCount(root.left, k-1)+getKLevelNodeCount(root.right, k-1); }
5. Obtenha a altura da árvore binária
Análise do pensamento:
código mostrar como abaixo:
// 获取二叉树的高度(时间复杂度为O(n)) int getHeight(BTNode root){ if(root==null){ return 0; } int leftHeight=getHeight(root.left); int rightHeight=getHeight(root.right); //此处用的是三目运算符求取两者中的较大值 return leftHeight>rightHeight?leftHeight+1:rightHeight+1; }
6. Verifique se o elemento cujo valor é valor existe
Ideias para resolução de problemas:
código mostrar como abaixo:
// 检测值为value的元素是否存在 boolean find(BTNode root, int val) { if (root == null) { return false; } else if (root.val == val) { return true; } if (find(root.left, val) || find(root.right, val)) { return true; } return false; }
7. Determine se uma árvore é uma árvore binária completa
Ideias para resolução de problemas:
código mostrar como abaixo:
boolean isCompleteTree(BTNode root){ if(root == null) return true; Queue<BTNode> queue = new LinkedList<>(); queue.offer(root); while (!queue.isEmpty()) { BTNode cur = queue.poll(); if(cur != null) { queue.offer(cur.left); queue.offer(cur.right); }else { break; } } //第二个while循环实质上就是在cur=null的基础上来判断实现的,若是整个为空即null 则true;反之为false while (!queue.isEmpty()) { BTNode top = queue.peek(); if(top != null) { return false; } queue.poll(); } return true; }
1. Verifique se duas árvores são iguais
100. A mesma árvore - LeetCode (leetcode-cn.com) https://leetcode-cn.com/problems/same-tree/
Ideias para resolução de problemas:
Para saber se duas árvores são iguais:
①A estrutura dos números é a mesma
②O valor correspondente ao nó na posição correspondente é o mesmo
código mostrar como abaixo:
public boolean isSameTree(TreeNode p, TreeNode q ){ if(p == null && q != null || p != null && q == null) { return false; } if(p == null && q == null) { return true; } if(p.val != q.val) { return false; } //p != null && q!= null && p.val == q.val return isSameTree(p.left,q.left) && isSameTree(p.right,q.right); }
2. Uma subárvore de outra árvore
código mostrar como abaixo:
public boolean isSubtree(TreeNode root, TreeNode subRoot) { if(root == null || subRoot == null) { return false; } //根节点和subroot是不是两颗相同的树 if(isSameTree(root,subRoot)) { return true; } //subRoot是不是root的左子树 if(isSubtree(root.left,subRoot)) { return true; } if(isSubtree(root.right,subRoot)) { return true; } return false; } }
3. Profundidade máxima da árvore binária
5 perguntas sobre o funcionamento básico da mesma árvore binária, consulte o topo deste blog
4. Determine se uma árvore binária é uma árvore binária balanceada
Ideias para resolução de problemas:
class Solution { public int height (TreeNode root) { if(root == null) {return 0;} int leftHeight = height(root.left); int rightHeight = height(root.right); return (leftHeight > rightHeight) ? (leftHeight+1) :(rightHeight+1); } /** 时间复杂度:O(N^2) */ public boolean isBalanced(TreeNode root) { if(root == null) return true; int left = height(root.left); int right = height(root.right); return Math.abs(left-right) <= 1 && isBalanced(root.left) && isBalanced(root.right); } }
5. Árvore Binária Simétrica
101. Árvore Binária Simétrica - LeetCode (leetcode-cn.com) https://leetcode-cn.com/problems/symmetric-tree/Ideias de solução :
código mostrar como abaixo:
class Solution { public boolean isSymmetric(TreeNode root) { if(root == null) return true; return isSymmetricChild(root.left,root.right); } public boolean isSymmetricChild(TreeNode leftTree,TreeNode rightTree) { //第一种情况 if(leftTree == null && rightTree == null) return true; //第二种情况 if((leftTree == null && rightTree != null)||(leftTree != null && rightTree == null)) return false; //第三种情况 if(leftTree.val != rightTree.val) return false; return isSymmetricChild(leftTree.left,rightTree.right) && isSymmetricChild(leftTree.right,rightTree.left); }
6. Construção e travessia da árvore binária
7. Percurso hierárquico da árvore binária
Ideias para resolução de problemas:
imprimir travessia hierárquica com a ajuda de uma fila e uma variável temporária cur
① Discuta se a raiz está vazia ou não
②Quando a fila não estiver vazia, retire o elemento final da fila para cur e imprima-o através de cur.val
③A situação das subárvores esquerda e direita é discutida em um loop, então use while para fazer um loop
Dois tipos de códigos:
①Código comum:
//打印层序遍历二叉树 public void levelOrder(TreeNode root) { Queue<TreeNode> queue = new LinkedList<>(); //①判断树是否为空的情况 if(root == null) return; queue.offer(root); //②判断队列是否为空 while (!queue.isEmpty()) { TreeNode cur = queue.poll(); System.out.print(cur.val+" "); if(cur.left != null) { queue.offer(cur.left); } if(cur.right != null) { queue.offer(cur.right); } } }
②O código para resolver o problema no JO:
Ideias para resolução de problemas:
código mostrar como abaixo:
//层序遍历访问打印元素 List<List<Integer>> ret = new ArrayList<>(); if(root == null) return ret; Queue<TreeNode> queue = new LinkedList<>(); queue.offer(root); while (!queue.isEmpty()) { //当前的结点个数size int size = queue.size(); List<Integer> list = new ArrayList<>(); while (size != 0) { TreeNode cur = queue.poll(); //将同层结点放在一个list中 list.add(cur.val); if(cur.left != null) { queue.offer(cur.left); } if(cur.right != null) { queue.offer(cur.right); } size--;//1 0 } //将所有一层link的结点放在同一个list中 ret.add(list); } //最后返回整个所需的ret return ret; }
8. Dada uma árvore binária, encontre o ancestral comum mais próximo de dois nós especificados na árvore
Ideias para resolução de problemas:
Ideia 1 : Um método de projetar uma árvore binária a partir da ideia de uma árvore de busca binária
Se uma árvore de busca binária
Ideias detalhadas:
1. root==p || root==q (p, q é um nó)
O ancestral comum mais próximo neste momento é a raiz
2. Pode estar à esquerda ou à direita da raiz
① p.val<root.val && q.val< root.val (p, q estão ambos na subárvore esquerda da raiz) o
ancestral comum mais próximo está na subárvore esquerda
②p.val>root.val && q.val>root.val (p, q estão ambos na subárvore direita da raiz)
O ancestral comum mais próximo está na subárvore direita
3. O ancestral comum mais próximo é a raiz
①p.val>root.val && q.val<root.val (p está na subárvore esquerda, q está na subárvore direita)
②p.val<root.val && q.val> root.val (p está na subárvore direita, q está na subárvore esquerda)
código mostrar como abaixo://二叉树的最近公共祖先 class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if(root==null){ return null; }if(root==p||root==q){ return root; } TreeNode l=lowestCommonAncestor(root.left,p,q); TreeNode r=lowestCommonAncestor(root.right,p,q); if(l!=null && r!=null){ return root; }else if(l!=null){ return l; }else{ return r; } } }
Pensamento ② :
Obtido da representação parental da criança
código mostrar como abaixo:
class Solution { //root: public boolean getPath(TreeNode root,TreeNode node,Stack<TreeNode>stack){ if(root==null || node==null){ return false; }stack.push(root); if(root==node){ return true; } boolean flg=getPath(root.left,node,stack); if(flg==true){ return true; } flg=getPath(root.right,node,stack); if(flg==true){ return true; } stack.pop(); return false; } public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if(root==null){ return null; } Stack<TreeNode> stack1=new Stack<>(); getPath(root,p,stack1); Stack<TreeNode> stack2=new Stack<>(); getPath(root,q,stack2); int size1=stack1.size(); int size2=stack2.size(); if(size1>size2){ int size=size1-size2; while(size!=0){ stack1.pop(); size--; } while(!stack1.isEmpty() && !stack2.isEmpty()){ //用等号判断地址 if(stack1.peek()==stack2.peek()){ return stack1.pop(); }else{ stack1.pop(); stack2.pop(); } } }else{ int size=size2-size1; while(size!=0){ stack2.pop(); size--; } while(!stack1.isEmpty() && !stack2.isEmpty()){ //用等号判断地址 if(stack1.peek()==stack2.peek()){ return stack1.pop(); }else{ stack1.pop(); stack2.pop(); } } } return null; } }
9. Converta a árvore de busca de árvore binária em uma lista duplamente ligada ordenada
link Niuke.com https://www.nowcoder.com/practice/947f6eb80d944a84850b0538bf0ec3a5?tpId=13&&tqId=11179&rp=1&ru=/activity/oj&qru=/ta/coding-interviews/question-ranking ideias para solução de problemas:
As características da árvore de busca binária foram introduzidas antes (por isso sabe-se que a árvore de busca binária é ordenada quando percorrida em ordem)
①Inorder travessia desta árvore binária
② Lista duplamente ligada
código mostrar como abaixo:
public class Solution { //先写出一个中序遍历 TreeNode prev=null; public void inOrder(TreeNode pCur){ if(pCur==null)return ; inOrder(pCur.left); pCur.left=prev; if(prev!=null){ prev.right=pCur; } prev=pCur; inOrder(pCur.right); } public TreeNode Convert(TreeNode pRootOfTree) { if(pRootOfTree==null){ return null; } inOrder(pRootOfTree); TreeNode head=pRootOfTree; while(head.left!=null){ head=head.left; } return head; } }
10. Construa uma árvore binária com base no percurso pré-ordem e no percurso inordenado de uma árvore
Ideias para resolução de problemas:
①Encontre o nó raiz
② Encontre as subárvores esquerda e direita através do percurso em ordem
③ Crie subárvores esquerda e direita respectivamente
código mostrar como abaixo:
class Solution { //将preIndex设置为全局变量用来保证在递归的过程中当子树根结点返回到总根后的空指针异常 public int preIndex=0; public TreeNode createTreeByPandI(int[]preorder,int[]inorder,int inbegin,int inend){ if(inbegin>inend){ //左树或者右树为空 return null; } TreeNode root=new TreeNode(preorder[preIndex]); int rootIndex=findIndexOfI(inorder,inbegin,inend,preorder[preIndex]); if(rootIndex==-1){ return null; } preIndex++; root.left=createTreeByPandI(preorder,inorder,inbegin,rootIndex-1); root.right=createTreeByPandI(preorder,inorder,rootIndex+1,inend); return root; } private int findIndexOfI(int[]inorder,int inbegin,int inend,int key){ for(int i=inbegin;i<=inend;i++){ if(inorder[i]==key){ return i; } } return -1; } public TreeNode buildTree(int[] preorder, int[] inorder) { if(preorder==null||inorder==null){ return null; }return createTreeByPandI(preorder,inorder,0,inorder.length-1); } }
11. Construir uma árvore binária com base na travessia em ordem e na travessia em pós-ordem de uma árvore
106. Construir árvore binária a partir da sequência de travessia inorder e pós-ordem - LeetCode (leetcode-cn.com) https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder- traversal/ problem- Resolvendo ideias:
Diferenças da pergunta anterior:
①postIndex está na extrema direita (ou seja, se o nó raiz for percorrido em pós-ordem, ele será percorrido um após o outro)
② Visite a árvore direita primeiro e depois a árvore esquerda
código mostrar como abaixo:
class Solution { public int postIndex=0; public TreeNode createTreeByPandI(int[]inorder,int[]postorder,int inbegin,int inend){ if(inbegin>inend){ //左树或者右树为空 return null; } TreeNode root=new TreeNode(postorder[postIndex]); int rootIndex=findIndexOfI(inorder,inbegin,inend,postorder[postIndex]); if(rootIndex==-1){ return null; } postIndex--; //分别创建右子树和左子树 root.right=createTreeByPandI(inorder,postorder,rootIndex+1,inend); root.left=createTreeByPandI(inorder,postorder,inbegin,rootIndex-1); return root; } private int findIndexOfI(int[]inorder,int inbegin,int inend,int key){ for(int i=inbegin;i<=inend;i++){ if(inorder[i]==key){ return i; } } return -1; } public TreeNode buildTree(int[] inorder, int[] postorder) { postIndex=postorder.length-1; if(postorder==null||inorder==null){ return null; }return createTreeByPandI(inorder,postorder,0,inorder.length-1); } }
12. Árvore binária para criar string
código mostrar como abaixo:
class Solution { public void treeToString(TreeNode t,StringBuilder sb) { if(t == null) return; sb.append(t.val); if(t.left != null) { sb.append("("); treeToString(t.left,sb); sb.append(")"); }else { //t.left == null if(t.right == null) { return; }else{ sb.append("()"); } } if(t.right == null) { return; }else{ sb.append("("); treeToString(t.right,sb); sb.append(")"); } } public String tree2str(TreeNode root) { if(root == null) return null; StringBuilder sb = new StringBuilder(); treeToString(root,sb); return sb.toString(); } }
13. Implementação não recursiva de pré-ordem de árvore binária
Ideias para resolução de problemas:
código mostrar como abaixo:
class Solution { public List<Integer> preorderTraversal(TreeNode root) { List<Integer>ret=new ArrayList<>(); Stack<TreeNode>stack=new Stack<>(); TreeNode cur = root; while (cur != null || !stack.isEmpty()) { while (cur != null) { stack.push(cur); ret.add(cur.val); cur = cur.left; } TreeNode top = stack.pop(); System.out.print(top.val+" "); cur = top.right; } return ret; }
14. Implementação transversal não recursiva em ordem de árvore binária
Ideia de solução de problemas: a mesma implementação de travessia não recursiva de pré-ordem de 13
código mostrar como abaixo:
class Solution { public List<Integer> inorderTraversal(TreeNode root) { List<Integer> ret= new ArrayList<>(); Stack<TreeNode> stack = new Stack<>(); TreeNode cur = root; while (cur != null || !stack.isEmpty()) { if (cur != null) { stack.push(cur); cur = cur.left; } else { cur = stack.pop(); ret.add(cur.val); cur = cur.right; } } return ret; } }