首页 > 编程语言 >面试最常见算法1—树—基础篇

面试最常见算法1—树—基础篇

时间:2023-02-17 19:38:32浏览次数:58  
标签:right return 常见 面试 算法 TreeNode null root left

前言

关于树的算法基本解法就三类:递归,队列,栈

刷题网站推荐:

1.二叉树遍历(前序)

public List<Integer> preorderTraversal(TreeNode root) {
// 1.递归实现
/**
List<Integer> res = new ArrayList<>();
if (null == root) {
return res;
}
res.add(root.val);
res.addAll(preorderTraversal(root.left));
res.addAll(preorderTraversal(root.right));
return res;
*/
// 2.使用栈实现
List<Integer> res = new ArrayList<>();
if (null == root) {
return res;
}
TreeNode head = root;
Stack<TreeNode> stack = new Stack<>();
while (null != head || !stack.isEmpty()) {
if (null != head) {
res.add(head.val);
stack.push(head);
head = head.left;
} else {
head = stack.pop().right;
}
}
return res;
}

前序遍历 ​https://leetcode.cn/problems/binary-tree-preorder-traversal/submissions/

中序遍历 ​https://leetcode.cn/problems/binary-tree-inorder-traversal/

后序遍历 ​https://leetcode.cn/problems/binary-tree-postorder-traversal/

2.二叉树层次遍历

public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if (root == null) {
return res;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
int len = queue.size();
List<Integer> item = new ArrayList<>();
while(len > 0){
//从队列中取出数据
TreeNode node = queue.poll();
item.add(node.val);
//边读边取
if(node.left != null){
queue.offer(node.left);
}
if(node.right != null){
queue.offer(node.right);
}
len--;
}
res.add(item);
}
return res;
}

https://leetcode.cn/problems/binary-tree-level-order-traversal/submissions/

其余的Z形打印或者锯齿打印都是它的变种

3.二叉树深度

public int maxDepth(TreeNode root) {
if (root == null)
return 0;
else {
int left = maxDepth(root.left);
int right = maxDepth(root.right);
return left > right ? left + 1 : right + 1;
}
}

https://leetcode.cn/problems/er-cha-shu-de-shen-du-lcof/

4.二叉树宽度

使用队列,层次遍历二叉树。在上一层遍历完成后,下一层的所有节点已经放到队列中,此时队列中的元素个数就是下一层的宽度。以此类推,依次遍历下一层即可求出二叉树的最大宽度。

public int widthOfBinaryTree(TreeNode root) {
if (root == null)
return 0;
Queue queue = new ArrayDeque();
int maxwitdth = 1; // 最大宽度
queue.add(root); // 入队
while (true) {
int len = queue.size(); // 当前层的节点个数
if (len == 0)
break;
while (len > 0) {// 如果当前层,还有节点
TreeNode t = (TreeNode) queue.poll();
len--;
if (t.left != null)
queue.add(t.left); // 下一层节点入队
if (t.right != null)
queue.add(t.right);// 下一层节点入队
}
maxwitdth = maxwitdth > queue.size() ? maxwitdth : queue.size();
}
return maxwitdth;
}

5.判断一棵树是否为另一棵树的子树

public boolean isSubtree(TreeNode root, TreeNode subRoot) {
if (root == null || subRoot == null) {
return false;
}
return isSameTree(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot);
}
public boolean isSameTree(TreeNode s, TreeNode t) {
if (t == null && s == null) {
return true;
}
if (s == null || t == null) {
return false;
}
return s.val == t.val && isSameTree(s.left, t.left) && isSameTree(s.right, t.right);
}

https://leetcode.cn/problems/subtree-of-another-tree/submissions/

6.二叉树的右视图

public List<Integer> rightSideView(TreeNode root) {
int cnt=0,tmp=0;
TreeNode node;
List<Integer> res = new LinkedList<>();
if(root==null){
return res;
}
Queue<TreeNode> queue=new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()){
cnt=queue.size();
while(cnt>0){
node=queue.poll();
if(node.left!=null)queue.offer(node.left);
if(node.right!=null)queue.offer(node.right);
cnt--;
tmp=node.val;
}
res.add(tmp);
}
return res;
}

https://leetcode.cn/problems/binary-tree-right-side-view/submissions/

7.给定n求二叉搜索树的个数

class Solution {
public int numTrees(int n) {
//初始化 dp 数组
int[] dp = new int[n + 1];
//初始化0个节点和1个节点的情况
dp[0] = 1;
dp[1] = 1;
for (int i = 2; i <= n; i++) {
for (int j = 1; j <= i; j++) {
//对于第i个节点,需要考虑1作为根节点直到i作为根节点的情况,所以需要累加
//一共i个节点,对于根节点j时,左子树的节点个数为j-1,右子树的节点个数为i-j
dp[i] += dp[j - 1] * dp[i - j];
}
}
return dp[n];
}
}

https://leetcode.cn/problems/unique-binary-search-trees/

8.二叉树的镜像

public TreeNode Mirror(TreeNode root) {
if (root == null)
return root;
swap(root);
Mirror(root.left);
Mirror(root.right);
return root;
}

private void swap(TreeNode root) {
TreeNode t = root.left;
root.left = root.right;
root.right = t;
}

https://www.nowcoder.com/practice/a9d0ecbacef9410ca97463e4a5c83be7?tpId=13&tqId=11171&tab=answerKey&from=cyc_github

9.对称的二叉树

boolean isSymmetrical(TreeNode pRoot) {
if (pRoot == null)
return true;
return isSymmetrical(pRoot.left, pRoot.right);
}

boolean isSymmetrical(TreeNode t1, TreeNode t2) {
if (t1 == null && t2 == null)
return true;
if (t1 == null || t2 == null)
return false;
if (t1.val != t2.val)
return false;
return isSymmetrical(t1.left, t2.right) && isSymmetrical(t1.right, t2.left);
}

https://www.nowcoder.com/practice/ff05d44dfdb04e1d83bdbdab320efbcb?tpId=13&tqId=11211&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking&from=cyc_github

10.二叉搜索树的第K个节点

由于是二叉搜索树,采用中序遍历得到的第k个节点即第k小的值,判断输出是否是第k个就可以返回值了,使用栈来辅助遍历

public int KthNode (TreeNode proot, int k) {
if (proot == null) return -1;
//中序遍历,第k个节点
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(proot);
TreeNode node = proot;
int i = 0;
while (!stack.isEmpty()) {
//遍历node下的所有左节点
while (node.left != null) {
stack.push(node.left);
node = node.left;
}
i++;
if (i == k) return stack.pop().val;
TreeNode tmp = stack.pop();
//加入右子树
if (tmp.right != null) {
stack.push(tmp.right);
node = tmp.right;
}
}
return -1;
}

https://www.nowcoder.com/practice/57aa0bab91884a10b5136ca2c087f8ff?tpId=13&tqId=2305268&ru=%2Fpractice%2F57aa0bab91884a10b5136ca2c087f8ff&qru=%2Fta%2Fcoding-interviews%2Fquestion-ranking&sourceUrl=

11.判断是不是平衡二叉树

private boolean isBalanced = true;

public boolean IsBalanced_Solution(TreeNode root) {
getHeight(root);
return isBalanced;
}

public int getHeight(TreeNode root) {
if(root == null) {
return 0;
}
int left = getHeight(root.left);
int right = getHeight(root.right);

if(Math.abs(left - right) > 1) {
isBalanced = false;
}

return 1 + Math.max(left, right);
}

https://www.nowcoder.com/practice/8b3b95850edb4115918ecebdf1b4d222?tpId=13&tqId=11192&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking&from=cyc_github

标签:right,return,常见,面试,算法,TreeNode,null,root,left
From: https://blog.51cto.com/u_13222507/6061711

相关文章

  • 经典算法之深度优先搜索(DFS)
    一、前言本文介绍了经典搜索算法:深度优先搜索(DFS)两个小故事:岳云鹏的相声:孙越的爸爸带他参观家里面的聚宝盆,走到了一个密室门前,密室的门上上了一把锁,孙越的爸爸身上带......
  • 经典算法之二分法
    二分法原理我们假设一下,你的女朋友买了件衣服,告诉你衣服的价格在200~2000之间,让你猜这件衣服的价格,怎么猜才能猜的最快呢?正确答案是:不猜,直接给女朋友转2000(手动狗头)。......
  • hadoop组件面试常见问题
    1、谈谈对HDFS的理解?HDFS这种存储适合哪些场景?HDFS即HadoopDistributedFileSystem,Hadoop分布式文件系统。它为的是解决海量数据的存储与分析的问题,它本身是源于Goole在......
  • 前端常见面试题(三)深拷贝代码
    constobj1{age:20,name:'xxx',address:{city:'beijing'}arr:['a','b','c']}constobj2=obj1obj2.address.city='shangh......
  • 只有五行的算法----Floyd-Warshall
    上图为一个城市地图,图中有4个城市,8条公路,公路上的数字表示这条公路的长短,并且这些公路是单向的,我们现在要求出任意两个城市之间的最短路径,也就是求任意两点的最短路径。我......
  • 前端常见面试题(二)CSS
    1、(布局)盒模型宽度计算offsetwidth=(内容宽度+内边距+边框),无外边距。100+10*2+1*2=122px 补充:如果让offsetwith=100px该如何做?添加box-sizing=border-box 2、(布......
  • 滑动窗口算法-找出字符串中无重复的最长字符串
    functionlengthOfLongestSubstring($s):string{$max=0;//返回结果,初始化为0$len=strlen($s);//传入的字符串长度$str='';//维护的滑动窗口......
  • JavaScript常见问题梳理
    1、this指向1、全局函数this指向全局对象window,注意严格模式下,this为undefined//[objectWindow]alert(this);functionf(){alert(this)}f()//undefinedfu......
  • 拜占庭将军问题和 Raft 共识算法讲解
    作者:京东物流郭益如导读在分布式系统中,什么是拜占庭将军问题?产生的场景和解决方案是什么?什么是Raft共识算法?Raft算法是如何解决拜占庭将军问题的?其核心原理和算法......
  • LS信道估计,MMSE信道估计以及CS信道估计算法的误码率对比仿真
    up目录一、理论基础二、核心程序三、测试结果一、理论基础所谓信道估计,就是从接收数据中将假定的某个信道模型的模型参数估计出来的过程。如果信道是线性的话,那......