Java 数据结构与算法-08——面试题解析(二叉树、二叉搜索树)
2019-05-20 19:57
441 查看
借参加过的多场Java开发面试,应聘岗位均为Java开发方向,在不断的面试中,又仔细对Java知识点进行复习和总结,也算是重新学习一下Java吧。
推荐收藏链接:Java 面试知识点解析
Java数据结构与算法知识点
1.二叉树的中序遍历
我的答案:(1ms)
public List<Integer> inorderTraversal(TreeNode root) { List result = new ArrayList(); if (null != root) { result.addAll(inorderTraversal(root.left)); result.add(root.val); result.addAll(inorderTraversal(root.right)); } return result; }
参考答案:(0ms)
public List<Integer> inorderTraversal(TreeNode root) { List<Integer> list=new ArrayList<>(); traversal(root, list); return list; } public void traversal(TreeNode root,List<Integer> list) { if(root!=null){ traversal(root.left, list); list.add(root.val); traversal(root.right, list); } }
2. 验证二叉搜索树
我的答案:(53ms)
private static int INT_MIN = Integer.MIN_VALUE; private static int INT_MAX = Integer.MAX_VALUE; public boolean isValidBST(TreeNode root) { // 如果节点为空则满足二叉搜索树条件 if (null == root) { return true; } // 如果左孩子结点大于了根节点则返回false if (null != root.left && findMax(root.left) > root.val) { return false; } // 如果右孩子结点小于了根节点则返回false if (null != root.right && findMin(root.right) < root.val) { return false; } // 递归判断左子树和右子树,若其中有一颗不是BST树,则返回false if (!isValidBST(root.left) || !isValidBST(root.right)) { return false; } // 通过所有判断则是一颗BST树 return true; } /** * 找到一颗非空树中的最大值 * * @param root * @return */ private int findMax(TreeNode root) { int maxVal = INT_MIN; int leftMaxVal = INT_MIN; int rightMaxVal = INT_MIN; if (null != root) { // 最大值默认等于当前节点值 maxVal = root.val; leftMaxVal = findMax(root.left); rightMaxVal = findMax(root.right); // maxVal等于当前maxVal与leftMaxVal中较大的一个 maxVal = maxVal > leftMaxVal ? maxVal : leftMaxVal; // maxVal等于当前maxVal与rightMaxVal中较大的一个 maxVal = maxVal > rightMaxVal ? maxVal : rightMaxVal; } return maxVal; } /** * 找到一颗非空树的最小值 * * @param root * @return */ private int findMin(TreeNode root) { int minVal = INT_MAX; int leftMinVal = INT_MAX; int rightMinVal = INT_MAX; if (null != root) { // 最小值默认为当前节点值 minVal = root.val; leftMinVal = findMin(root.left); rightMinVal = findMin(root.right); // minVal等于当前minVal与leftMinVal中较小的一个 minVal = minVal < leftMinVal ? minVal : leftMinVal; // minVal等于当前minVal与rightMinVal中较小的一个 minVal = minVal < rightMinVal ? minVal : rightMinVal; } return minVal; }
参考答案:(2ms)
public boolean isValidBST(TreeNode root) { if (root == null) return true; return valid(root, Long.MIN_VALUE, Long.MAX_VALUE); } public boolean valid(TreeNode root, long low, long high) { if (root == null) return true; if (root.val <= low || root.val >= high) return false; return valid(root.left, low, root.val) && valid(root.right, root.val, high); }
这答案写得我服了…真服…
3. 对称二叉树
参考答案:(12ms)
public boolean isSymmetric(TreeNode root) { return isSymmetric(root, root); } public boolean isSymmetric(TreeNode root1, TreeNode root2) { if (null == root1 && null == root2) { return true; } if (null == root1 || null == root2) { return false; } if (root1.val != root2.val) { return false; } return isSymmetric(root1.left, root2.right) && isSymmetric(root1.right, root2.left); }
4. 二叉树的最大深度
我的答案:(3ms)
public int maxDepth(TreeNode root) { int leftHeight, rightHeight; if (null == root) { return 0; } else { // 计算每个子树的高度 leftHeight = maxDepth(root.left); rightHeight = maxDepth(root.right); return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1; } }
参考答案:(0ms)
public int maxDepth(TreeNode root) { if(root==null) return 0; return Math.max(maxDepth(root.left)+1,maxDepth(root.right)+1); }
5. 从前序与中序遍历序列构造二叉树
参考答案:(2ms)
public TreeNode buildTree(int[] preorder, int[] inorder) { if (preorder == null || preorder.length == 0) { return null; } return buildTree(preorder, inorder, 0, 0, inorder.length - 1); } private TreeNode buildTree(int[] preorder, int[] inorder, int ps, int is, int ie) { int val = preorder[ps]; TreeNode node = new TreeNode(val); int iRoot = ie; while (iRoot > is) { if (val == inorder[iRoot]) { break; } iRoot--; } if (iRoot > is) { node.left = buildTree(preorder, inorder, ps + 1, is, iRoot - 1); } if (iRoot < ie) { node.right = buildTree(preorder, inorder, ps + 1 + (iRoot - is), iRoot + 1, ie); } return node; }
思路是这样的:在二叉树的前序遍历序列中,第一个数字总是树的根节点的值,但在中序遍历序列中,根节点的值保存在序列的中间,左子树的节点的值位于根节点的值的左边,而右子树则相反,然后既然找到了左右子树我们又可以使用同样的方法在前序和中序中分别构建左右子树,这样我们就能够使用递归的方法完成;(上面算法中的ps、is、ie分别表示前序的开始位置,中序的开始位置和中序的结束位置;)
6. 路径总和
参考答案:(3ms)
public List<List<Integer>> pathSum(TreeNode root, int sum) { List<Integer> nodeList = new ArrayList<Integer>(); List<List<Integer>> sumList = new ArrayList<List<Integer>>(); if (root == null) { return sumList; } pathSum2(root, sum, sumList, nodeList); return sumList; } public void pathSum2(TreeNode root, int target, List<List<Integer>> sumList, List<Integer> nodeList) { if (root.left == null && root.right == null) { nodeList.add(root.val); int sum = 0; for (Integer integer : nodeList) { sum += integer; } if (sum == target) { sumList.add(new ArrayList<Integer>(nodeList)); } return; } nodeList.add(root.val); if (root.left != null) { pathSum2(root.left, target, sumList, nodeList); nodeList.remove(nodeList.size() - 1); } if (root.right != null) { pathSum2(root.right, target, sumList, nodeList); nodeList.remove(nodeList.size() - 1); } }
7. 二叉搜索树中第K小的元素
我的答案:(23ms)
public int kthSmallest(TreeNode root, int k) { // 正确性判断 if (null == root || k < 1) { return -1; } List<Integer> result = preOrder(root); // 从小到大排序 Collections.sort(result); return result.get(k - 1); } /** * 遍历整棵树并返回一个List * * @param root * @return */ private List<Integer> preOrder(TreeNode root) { List result = new ArrayList(); if (null != root) { result.add(root.val); result.addAll(preOrder(root.left)); result.addAll(preOrder(root.right)); } return result; }
参考答案:(1ms)
public int kthSmallest(TreeNode root, int k) { int count = countNodes(root.left); if (k <= count) { return kthSmallest(root.left, k); } else if (k > count + 1) { return kthSmallest(root.right, k - 1 - count); } return root.val; } public int countNodes(TreeNode n) { if (n == null) return 0; return 1 + countNodes(n.left) + countNodes(n.right); }
8. 序列化二叉搜索树
参考答案:(12ms)
// Encodes a tree to a single string. public String serialize(TreeNode root) { StringBuffer sb = new StringBuffer(); preOrder(root,sb); return sb.toString(); } private static void preOrder(TreeNode root, StringBuffer sb){ if(root==null) return; sb.append(root.val).append('#'); preOrder(root.left,sb); preOrder(root.right,sb); } // Decodes your encoded data to tree. public TreeNode deserialize(String data) { if(data==null) return null; int val =0; TreeNode root = null; for(int i=0;i<data.length();i++){ if(data.charAt(i)!='#'){ val = val*10+(data.charAt(i)-'0'); }else{ root = insert(root,val); val=0; } } return root; } private static TreeNode insert(TreeNode root,int val){ if(root==null) return new TreeNode(val); if(root.val<val) root.right = insert(root.right,val); else root.left = insert(root.left,val); return root; }
9. 另一个树的子树
参考答案:(15ms)
public boolean isSubtree(TreeNode s, TreeNode t) { // Write your code here if (s == null) { return t == null; } if (s.val == t.val && isSametree(s, t)) { return true; } return isSubtree(s.left, t) | isSubtree(s.right, t); } private boolean isSametree(TreeNode s, TreeNode t) { if (s == null) { return t == null; } if (t == null) { return false; } if (s.val != t.val) { return false; } return isSametree(s.left, t.left) & isSametree(s.right, t.right); }
我的第一个反应还是去把两棵树的前序遍历的数组弄出来然后判断是否为子集,但是树这样的天然递归结构这样写很自然…
我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家。扫描二维码加VX好友,拉你进【程序员面试学习交流群】免费领取。也欢迎各位一起在群里探讨技术。
相关文章推荐
- Java数据结构与算法解析(五)——二叉查找树
- Java数据结构与算法解析(三)——队列与背包
- Java数据结构与算法解析——优先级队列
- Java数据结构与算法解析(九)——B树
- Java数据结构与算法解析(十五)——左式堆
- Java数据结构与算法解析(十四)——二叉堆
- 面试准备--数据结构与算法(二)--栈的图文解析及其java实现
- 【算法学习笔记】08.数据结构基础 二叉树初步练习1
- Java数据结构与算法解析(十)——2-3树
- 数据结构与算法经典问题解析 Java语言描述pdf
- Java数据结构与算法解析——2-3树
- Java数据结构与算法解析(一)——表
- Java数据结构与算法解析(八)——伸展树
- Java数据结构与算法解析(十)——2-3树
- Java数据结构与算法解析(三)——队列与背包
- Java数据结构与算法解析(八)——伸展树
- Java数据结构与算法解析(五)——二叉查找树
- 【算法学习笔记】08.数据结构基础 二叉树初步练习1
- 【数据结构与算法】二叉树的Java实现及特点总结
- Java数据结构与算法解析(十一)——红黑树