leetcode树有关题目随笔
2019/11/22
109题 没想到用两个指针 好在可以自己想出点东西 但是是错的错误如下:
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public TreeNode sortedListToBST(ListNode head) { int len = 1; ListNode cur = head; while(cur.next!=null){ len +=1; cur=cur.next; } return sortedListToBST(head,0,len); } private TreeNode sortedListToBST(ListNode head,int start,int end){ int mid=(start+end)>>>1; ListNode cur = head; int i=mid; while(i>0){ cur=cur.next; i--; } TreeNode root = new TreeNode(cur.val); root.left=sortedListToBST(head,start,mid-1); root.right=sortedListToBST(cur,mid+1,end); return root; } }
注意体会官方解法方法 3:中序遍历模拟用到的思想。
1做过数组还原平衡二叉搜索树(推荐先做题号108),我们知道,在array中每次取中点作为根节点,左右分别构建左右子树,递归直至根节点为空。
2链表的特性导致我们无法像数组那样通过下标访问各个元素。若想按照108题的做法,就需要设置两个指针p1 p2,p1每走一步p2走两步,这样p2结束时p1就在中点。但这样会导致每次递归都需要重复遍历链表,效率较低。
3我们考虑是否可以让建立节点的顺序匹配链表元素顺序?这样每次建立节点时,只需要获取链表下一个元素即可。
4使用递归模拟中序遍历过程,建立节点的顺序即与链表元素顺序一一对应,bottom-up建立树,最终返回根节点。
5递归前需要统计链表长度n,整体算法复杂度O(N)。
===========================================
后序遍历的代码
public void PrintBinaryTreeBacRecur(TreeNode<T> root){ if (root == null) return; PrintBinaryTreeBacRecur(root.right); PrintBinaryTreeBacRecur(root.left); System.out.print(root.data); }
先序遍历迭代
public static void preOrderStack(TreeNode root) { if (root == null) { return; } Stack<TreeNode> s = new Stack<TreeNode>(); while (root != null || !s.isEmpty()) { while (root != null) { System.out.println(root.val); s.push(root); root = root.left; } root = s.pop(); root = root.right; } }
还有一种特殊的先序遍历,提前将右孩子保存到栈中,我们利用这种遍历方式就可以防止右孩子的丢失了。由于栈是先进后出,所以我们先将右节点入栈。
public static void preOrderStack(TreeNode root) { if (root == null){ return; } Stack<TreeNode> s = new Stack<TreeNode>(); s.push(root); while (!s.isEmpty()) { TreeNode temp = s.pop(); System.out.println(temp.val); if (temp.right != null){ s.push(temp.right); } if (temp.left != null){ s.push(temp.left); } } }
作者:windliang
链接:https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by--26/
来源:力扣(LeetCode)
==============================================
作者:powcai
链接:https://leetcode-cn.com/problems/path-sum-ii/solution/dfs-by-powcai-2/
来源:力扣(LeetCode)
class Solution { public List<List<Integer>> pathSum(TreeNode root, int sum) { List<List<Integer>> res = new ArrayList<>(); helper(root, sum, res, new ArrayList<Integer>()); return res; } private void helper(TreeNode root, int sum, List<List<Integer>> res, ArrayList<Integer> tmp) { if (root == null) return; tmp.add(root.val); if (root.left == null && root.right == null && sum - root.val == 0) res.add(new ArrayList<>(tmp)); helper(root.left, sum - root.val, res, tmp); helper(root.right, sum - root.val, res, tmp); tmp.remove(tmp.size() - 1); } }
仿照答案中更快的写法在helper中加了一个返回结果更快
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public List<List<Integer>> pathSum(TreeNode root, int sum) { List<List<Integer>> res = new ArrayList<>(); helper(root,sum,res,new ArrayList<Integer>()); return res; } public void helper(TreeNode root,int sum,List<List<Integer>> res, ArrayList<Integer> tmp){ if(root==null) return; tmp.add(root.val); if(root.left==null&&root.right==null&&sum-root.val==0) { res.add(new ArrayList<>(tmp)); tmp.remove(tmp.size()-1); return; } helper(root.left,sum-root.val,res,tmp); helper(root.right, sum - root.val, res, tmp); tmp.remove(tmp.size() - 1); } }
94. 二叉树的中序遍历 2020/1/7
二叉树的前序中序后序遍历还需要巩固巩固 一开始想到了递归的方法,但是没想出来代码
递归方法(基本方法)、迭代方法(迭代就是使用栈来做,这个思想好好学习学习)
96. 不同的二叉搜索树 2020/1/7
遍历每个数字 i
,将该数字作为树根,1 ... (i-1)
序列将成为左子树,(i+1) ... n
序列将成为右子树 这个想法必修得有
笛卡尔积 由于 G(n)G(n) 和序列的内容无关,只和序列的长度有关 所以从 [4, 5, 6, 7]` 构建不同右子树的数量表示为 G(4)
或者是又叫做卡特兰数?
98. 验证二叉搜索树 2020/1/7
一般的迭代方法肯定要会把 类似于94题 用栈迭代
中序遍历 牛 那个方法要掌握并能想起来 按照12345在前序 中序 后序中的遍历顺序来检验
最大值 最小值的方法真的绝了
100. 相同的树 2020/1/8
这里有一个大佬给的关于树的解题模板
void BST(TreeNode root, int target) { if (root.val == target) // 找到目标,做点什么 if (root.val < target) BST(root.right, target); if (root.val > target) BST(root.left, target); }
101. 对称二叉树 2020/1/8
注意审题!
102. 二叉树的层次遍历 2020/1/8
用队列来做的想法想到了 棒棒 再加一个单独的变量记录把数据放在第几个内部list中
103. 二叉树的锯齿形层次遍历 2020/1/9
list的add方法有两种方法,一个是add(E element)一个是add(int index,E element)
然后就可通过一个值判断是从左往右还是从右往左 然后通过不同的add来添加数值
或者是用addFirst和add来分别往list中添加数值
104. 二叉树的最大深度 2020/1/9
我靠 这个我没想到 官方解答的第一个方法 深度优先遍历 呜呜呜这么简单
105. 从前序与中序遍历序列构造二叉树 2020/1/30
答主给的方法很多 采用了第二种使用HashMap的方法
106. 从中序与后序遍历序列构造二叉树 2020/1/30
使用到技巧 通过解方程得到下标 使用hash表能使速度更快一些 答案里有的答案更快
107. 二叉树的层次遍历 II 2020/1/31
BFS思想能想到 queue输入是offer!!! DFS思想 用level来控制 对于从下往上的输出 可以在list中采用add(index,new arraylist)的方法
108. 将有序数组转换为二叉搜索树 2020/1/31
这道题很简单的只用进行递归即可。不用想的复杂 计算一个mid值分左右
109. 有序链表转换二叉搜索树 2020/1/31
中序遍历模拟的方法很经典 注意node是在left_child后面进行计算的
110. 平衡二叉树 2020/2/1
从顶到底的思想 暴力法 结合104二叉树最大深度来考虑
或者是从底到顶的思想 也就是DFS 值得好好揣摩
111. 二叉树的最小深度 2020/2/1
当前节点左右子树
有一个为空时,返回的应是非空子树
的最小深度,而不是空子树
深度0;若返回0相当于把当前节点认为成叶子节点
,与此节点有非空子树
矛盾。
112. 路径总和 2020/2/2
还不错 能想到
113. 路径总和 II 2020/2/2
回溯回溯回溯!!!
114. 二叉树展开为链表 2020/2/2
找到技巧