前言
最近在刷LeetCode每日一题,每次做完之后总能有些收获,所以想着不如每天写个博客记录一下做的题目的解法以及自己写的时候问题出在哪里。
题目
题目大意:
给出一个字符串"1-2–3--4-5–6--7",1代表节点的值,前面的-
个数代表节点的深度。如果只有一个子节点,保证这个节点为左子节点。
返回一个二叉树。
思路
一看到树的题目,首先就想到了使用递归。
这道题显然是不断递归生成子节点,那首先需要把一些值设置为全局变量。
需要设置为全局变量的值有
index
:当前字符位。chars
:字符数组。
然后对于一次递归来说,首先要获得当前节点的值。
这边需要注意当前节点的值可能不止一位,那么需要判断当前位置的值是否为数字,如果是的话则保存下来并且将index++
,然后最后获得一个整数,同时要注意index不要越界了。
接下来判断后面有多少个’-’,如果个数为当前deep+1
,那说明是左子树,进行递归。
如果不是,那么说明是当前节点的兄弟节点,或者父节点的兄弟,总之说明该节点没有子树了,就需要返回。
对于右子树来说也是同样的操作。
这里要注意index
的值,不要越界了,一旦判断index >= length
就说明这是最后一个节点,直接返回该节点。
代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
int index = 0;
char[] chars;
public TreeNode recoverFromPreorder(String S) {
if(S == null || S.length() == 0)
return null;
index = 0;
chars = S.toCharArray();
return pre(1);
}
public TreeNode pre(int deep){
if(index >= chars.length)
return null;
int val = 0;
while(index < chars.length && chars[index] != '-'){
val *= 10;
val += chars[index]-'0';
index++;
}
TreeNode node = new TreeNode(val);
for(int i=0;i<deep;i++){
if(index >= chars.length || chars[index+i] != '-')
return node;
}
index += deep;
node.left = pre(deep+1);
for(int i=0;i<deep;i++){
if(index >= chars.length || chars[index+i] != '-')
return node;
}
index += deep;
node.right = pre(deep+1);
return node;
}
}
错误
这次代码中主要犯了如下错误:
在void
类型的方法中修改对象,我写了如下代码:
public void mian(){
TreeNode root = new TreeNode(1);
getLeft(root.left);
}
public void getLeft(TreeNode node){
node = new TreeNode(0);
}
在这个代码我想实现生成一个新的TreeNode
并且赋值给root
的左子树。但是这样并不能成功,root
左子树还是null
。
这是因为当我将root.left
传递给子方法的时候,子方法生成了一个局部变量node
,并且将node
的地址设置为root.left
的地址也就是null。
当我执行node = new TreeNode(0);
的时候我把node
的地址又修改为了新生成的节点的地址TreeNode@4141d797
(这是我在idea中输出的地址,实际不一定是这个)。
但是这个时候node.left
依然还是null
没有得到修改,所以方法返回之后什么也没有发生。
正确的代码写法应该如下:
public void mian(){
TreeNode root = new TreeNode(1);
//这样就是将root.left的地址修改为node的地址,所以不会出错。
root.left = getLeft();
}
public TreeNode getLeft(){
node = new TreeNode(0);
return node;
}
后记
这次错误的原理其实早就在书上看到过了,但是实际写的时候还是犯了,果然是“纸上得来终觉浅,绝知此事要躬行”。
看了半天感觉没什么问题,一调试就发现了问题所在,感觉非常睿智。
总之,今天的题得到了如下收获:
- 想递归生成一个新的对象,老老实实返回,不要用
void
方法然后在里面生成。 - 看到字符串整数的时候,一定注意整数长度可能不止一位,leetcode的题老是只给你一位整数误导你,其实测试用例里有好多多位整数,这个时候需要先获得整个整数的位数然后再处理。
- 判断index是否越界。