今天仍然打卡代码随想录和JVM的视频。
1.合并二叉树(力扣617)
思路:合并到第一棵树上,若合并时其中一个为空,则返回另一个,均不为空时将第二棵树的值加到第一个树的值上。
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) { if(root1 == null && root2 == null) return null; else if(root1 != null && root2 == null) { root1.left = mergeTrees(root1.left,root2); root1.right = mergeTrees(root1.right,root2); } else if(root1 == null && root2 != null) { root1 = new TreeNode(root2.val); root1.left = mergeTrees(root1.left,root2.left); root1.right = mergeTrees(root1.right,root2.right); } else { root1.val += root2.val; root1.left = mergeTrees(root1.left,root2.left); root1.right = mergeTrees(root1.right,root2.right); } return root1; }
*2.二叉树的中序遍历
今天回顾了二叉树的中序遍历,利用递归的方法很好解决,这里主要是学习非递归的方法。主要思路是先把左边的放入栈,若没有在左边的了就弹出栈顶元素,将其右边的元素作为下一个入栈元素,该元素继续入栈后继续将其左边元素入栈。。。以此遍历至整棵树结束。
public ListinorderTraversal(TreeNode root) { // List res = new ArrayList<>(); // if (root == null) // return res; // midOrder(root,res); // return res; List result = new ArrayList<>(); if (root == null){ return result; } Stack stack = new Stack<>(); TreeNode cur = root; while (cur != null || !stack.isEmpty()){ //栈不为空且放入元素不为空时一直循环 if (cur != null){ stack.push(cur); cur = cur.left; }else{ cur = stack.pop(); result.add(cur.val); cur = cur.right; } } return result; }
*3.二叉树的前序遍历
仍然采用非递归的方法,进栈顺序为中右左(保证出栈是中左右)。
class Solution { public ListpreorderTraversal(TreeNode root) { List res = new ArrayList<>(); Deque deque = new ArrayDeque<>(); if (root == null) return res; deque.push(root); while (!deque.isEmpty()){ TreeNode t = deque.pop(); res.add(t.val); if(t.right != null) deque.push(t.right); if(t.left != null) deque.push(t.left); } return res; } }
*4二叉树的后序遍历
依然采用非递归,进栈顺序为中左右(保证出栈顺序为中右左,再反转为左右中)
class Solution { public ListpostorderTraversal(TreeNode root) { List res = new ArrayList<>(); if(root == null) return res; Deque deque = new ArrayDeque<>(); deque.push(root); while (!deque.isEmpty()){ TreeNode t = deque.pop(); res.add(t.val); if(t.left != null) deque.push(t.left); if(t.right != null) deque.push(t.right); } Collections.reverse(res); return res; } }
5.二叉搜索树的最小绝对差(力扣530)
可以将二叉搜索树变成一个数组然后遍历数组获得最小绝对差,也可以在遍历搜索树时记录前驱指针,计算前驱与当前节点的差值,保留最小。
class Solution { public int getMinimumDifference(TreeNode root) { Listres = new ArrayList<>(); Deque deque = new ArrayDeque<>(); TreeNode pre = null; while (!deque.isEmpty() || root != null) { if(root!=null) { deque.push(root); root = root.left; } else { root = deque.pop(); if(pre!=null){ res.add(Math.abs(root.val - pre.val)); } pre = root; root = root.right; } } // List list = new ArrayList<>(); // for (int i = 0; i < res.size()-1; i++) { // list.add(Math.abs(res.get(i)-res.get(i+1))); // } Collections.sort(res); return res.get(0); } }
6.二叉搜索树中的众数(力扣501)
由于是二叉搜索树,用中序遍历一遍后并用map存放每个元素出现的次数,存放时判断次数是否已经达到当前最大值,达到了则加入数组,超过则清空数组后加入数组,保证数组中始终存放当前的众数。
class Solution { public int[] findMode(TreeNode root) { Listarr = new ArrayList<>(); HashMap hashMap = new HashMap<>(); midOrder(root,arr); int max = Integer.MIN_VALUE; List list = new ArrayList<>(); for (int i = 0; i < arr.size(); i++) { int t = hashMap.getOrDefault(arr.get(i),0)+1; hashMap.put(arr.get(i),hashMap.getOrDefault(arr.get(i),0)+1); if(t>max) { list.clear(); list.add(arr.get(i)); max = t; } else if(t==max) { list.add(arr.get(i)); } } int[] res = new int[list.size()]; for (int i = 0; i < list.size(); i++) { res[i] = list.get(i); } return res; } public void midOrder(TreeNode treeNode, List list){ if(treeNode == null) return; midOrder(treeNode.left,list); list.add(treeNode.val); midOrder(treeNode.right,list); } }
*7.二叉树的最近公共祖先(力扣236)
思路:找到根到两个节点的路径,路径中最后相交的节点即为最近的公共祖先。主要利用了回溯法。
class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { Listpath1 = new ArrayList<>(); List path2 = new ArrayList<>(); List > l1 = new ArrayList<>(); List
> l2 = new ArrayList<>(); getPath(root,p.val,path1,l1); getPath(root,q.val,path2,l2); int len; if (l1.get(0).size()>=l2.get(0).size()) len = l2.get(0).size(); else len = l1.get(0).size(); for (int i = len-1; i > 0 ; i--) { if(l1.get(0).get(i) == l2.get(0).get(i) ) return l1.get(0).get(i); } return root; } public void getPath(TreeNode treeNode, int val, List
list,List > l){ if(treeNode == null) return; if(treeNode.val == val){ list.add(treeNode); l.add(new ArrayList<>(list));//在成功找到,添加路径时记得要new新的对象添加,直接添加list是错误的,只是将list的地址值传了进来,后续会被更改。 list.remove(treeNode); return; } if(treeNode.left != null) { list.add(treeNode); getPath(treeNode.left,val,list,l); list.remove(treeNode); } if (treeNode.right != null){ list.add(treeNode); getPath(treeNode.right,val,list,l); list.remove(treeNode); } return; } }
8.二叉搜索树的最近公共祖先(力扣235)
这个比寻找普通二叉树的最近公共祖先简单很多,若根节点为两个元素之一,直接返回;若两个元素分别在根的两侧,也直接返回根节点;否则递归地遍历根节点的左边或者右边。
class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if(root == null) return null; if(root.val == p.val || root.val == q.val) return root; if((p.valroot.val) || (p.val>root.val && q.val