leetcode深度优先遍历学习2
昨天做了几个比较简单的题。今天适当增加一点难度。
113.路径总和2
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
这个题很明显是要利用优先遍历来实现。思路也比较简单,当遍历到一个路径的结束时,比较当前路径和是否等于目标值。相等的话就把这条路径加入到结果集中。
class Solution {
public List<List<Integer>> pathSum(TreeNode root, int sum) {
List<List<Integer>> pathList = new LinkedList<>();
if(root == null){
return pathList;
}
List<Integer> path = new LinkedList<>();
getPath(pathList,path,root,sum,0);
return pathList;
}
public void getPath(List<List<Integer>> list,List<Integer> path,TreeNode root,int sum,int curSum){
curSum += root.val;
path.add(root.val);
if(root.left == null && root.right == null){
if(sum == curSum){
List<Integer> temp = new LinkedList<>();
for(int a : path){
temp.add(a);
}
list.add(temp);
}
}else{
if(root.left != null){
getPath(list,path,root.left,sum,curSum);
}
if(root.right != null){
getPath(list,path,root.right,sum,curSum);
}
}
path.remove(path.size() - 1);
curSum -= root.val;
}
}
二叉树展开为链表
给定一个二叉树,原地将它展开为链表。
第一眼看到这个题目,我的第一反应是把根节点的左右节点先变成链表,之后再把这两个链表拼接在一起。之后实现起来遇到了问题,想了很久还是没有解决的思路。最后参照了别人的做法才做出来。
思路是这样的:每次将一个节点的右节点拼接到左子树的最右节点上,之后再将左节点变为它的右节点,再将它的左节点设为null。
class Solution {
public void flatten(TreeNode root) {
while(root != null){
if(root.left != null){
TreeNode temp = root.left;
while(temp.right != null){
temp = temp.right;
}
temp.right = root.right;
root.right = root.left;
root.left = null;
}
root = root.right;
}
}
}
我觉得需要注意的一点是原地展开,而不是返回一个新的链表。
116. 填充每个节点的下一个右侧节点指针
给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。
我还是太菜了。这个题我是用了队列来实现了广度优先遍历。即借助了辅助空间,效率也不高。
class Solution {
public Node connect(Node root) {
if(root == null){
return root;
}
Queue<Node> queue = new LinkedList<>();
queue.offer(root);
Node pre = null;
int layer = 0;
while(!queue.isEmpty()){
int cur = (int)Math.pow(2,layer);
while(cur != 0){
Node node = queue.poll();
if(pre == null){
pre = node;
}else{
pre.next = node;
pre = node;
}
if(node.left != null){
queue.offer(node.left);
}
if(node.right != null){
queue.offer(node.right);
}
cur--;
}
pre = null;
layer++;
}
return root;
}
}
之后看了别人的实现思路,发现自己确实还是有很大不足。
因为是完美二叉树,所以节点的next存在两种情况。一种是一个节点的左右子节点,而另一种就是跨父节点的next(该节点的右节点与该节点的next节点的左节点)。
class Solution {
public Node connect(Node root) {
if(root == null){
return root;
}
if(root.left != null){
root.left.next = root.right;
if(root.next != null){
root.right.next = root.next.left;
}
connect(root.left);
connect(root.right);
}
return root;
}
}
129. 求根到叶子节点数字之和
给定一个二叉树,它的每个结点都存放一个 0-9 的数字,每条从根到叶子节点的路径都代表一个数字。
例如,从根到叶子节点路径 1->2->3 代表数字 123。
计算从根到叶子节点生成的所有数字之和。
说明: 叶子节点是指没有子节点的节点。
感觉这题和之前做的路径和的题有点类似。主要思路是深度遍历一条路径,当遍历到叶节点时,将这个数加入到列表(辅助存储)中。之后再将列表的所有值都加起来。
class Solution {
public int sumNumbers(TreeNode root) {
if(root == null){
return 0;
}
StringBuilder str = new StringBuilder();
ArrayList<Integer> list = new ArrayList<>();
getNums(root,str,list);
int sum = 0;
for(int a : list){
sum += a;
}
return sum;
}
public void getNums(TreeNode root,StringBuilder str,ArrayList<Integer> list){
str.append(root.val);
if(root.left == null && root.right == null){
list.add(Integer.parseInt(str.toString()));
}
if(root.left != null){
getNums(root.left,str,list);
}
if(root.right != null){
getNums(root.right,str,list);
}
str.delete(str.length() - 1,str.length());
}
}
emmm,我现在在做leetcode130题,但是被卡住了。临时有点事,先更到这,我明天继续做。
加油加油。