1028. 从先序遍历还原二叉树
题目分析
这个题其实跟我们之前序列化二叉树的题有点类似,这个题的难点在于怎么把对应的层次节点的父节点找出来,说实话想的有点久。
因为树的问题一般都是递归解决,所以我这次也是用了递归的方法。
具体来说就是
- 字符串的第一次出现的数字必定为当前树的根节点,因为他是前序遍历。
- 我们可以依赖一个标记来记录当前所要找的层次。
- 因为这个是一棵二叉树,所以每次只需要分成左子树和右子树即可。
- 另外题目说了优先构建左子树,所以我们在实现的时候也要注意这个点。
代码实现
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
/**
* 说实话代码写的挺烂的,不过AC了
* @param S
* @return
*/
public TreeNode recoverFromPreorder(String S) {
//处理空字符串
if(S.length() == 0){
return null;
}
return helper(S,1);
}
public TreeNode helper(String str, int level){
//如果字符串为空,说明这边已经不存在节点了,直接返回空
if(str.length() == 0){
return null;
}
int j = 0;
int num = 0;
//处理根节点,因为根据题目的描述,我们的值可能不止一位,所以要逐个计算第一个数的数值
while(j < str.length() && str.charAt(j) != '-'){
num = num * 10 + Integer.parseInt(String.valueOf(str.charAt(j)));
j++;
}
//创建根节点
TreeNode root = new TreeNode(num);
//这个是关键,我们定义一个指针,它的值为第一个数字结束的下标加当前的层数+1
//例如 1-2-5 我们第一个数字结束的下标是0当前层数为1,所以我们开始遍历的下标应该为0+1+1。
int i = j+level;
//我们采用分治法思想,每次都把字符串分成左子树和右子树来进行处理。
String left = "";
String right = "";
int count = 0;
//记录左边界
int lastIndex = i;
while(i < str.length() - 1){
//统计-出现的次数,当-出现的次数与层数相等,并且接下来的字符不是-,说明我们已经找到了右子树开始的下标
if(str.charAt(i) == '-'){
count++;
}else{
count = 0;
}
//在这里进行切割,要注意substring是左闭右开的
if(count == level && str.charAt(i+1) != '-'){
left = str.substring(lastIndex,i-level+1);
right = str.substring(i+1);
break;
}
i++;
}
//因为题目说明优先建立左子树,如果我们遍历整棵树都找不到右子树,说明剩余的字符串都是左子树
//这里要注意还需要判断lastIndex是否小于字符串长度,否则会有字符串越界问题
if(i >= str.length() - 1 && lastIndex < str.length()){
left = str.substring(lastIndex);
}
//递归建立左子树和右子树
root.left = helper(left,level+1);
root.right = helper(right,level+1);
//返回根节点
return root;
}
}
总结
这个题也不是很难,主要是考一种思维吧,不过最近做题的手感真的是越来越差了,这个题起码花了半个小时才写出来,哭了