題名
二分木をシリアル化する1つの方法は、プレオーダートラバーサルを使用することです。空でないノードに遭遇した場合、このノードの値を記録できます。空のノードの場合は、#などのタグ値レコードを使用できます。
_9_
/ \
3 2
/ \ /
4 1#6
/ \ / \ / \
####
たとえば、上記の二分木は文字列「9,3,4、#、#、1、#、#、2、#、6、#、#」にシリアル化できます。ここで、#は空のノードを表します。
カンマ区切りのシーケンスを指定して、それがバイナリツリーの正しいプレオーダーシリアル化であることを確認します。ツリーを再構築せずに実行可能なアルゴリズムを記述します。
コンマで区切られた各文字は、整数またはヌルポインターを表す「#」のいずれかです。
入力形式は常に有効であると考えることができます。たとえば、「1,3」のように2つの連続したコンマが含まれることはありません。
例1:
入力: "9,3,4、#、#、1、#、#、2、#、6、#、#"
出力:true
例2:
入力: "1、#"
出力:false
例3:
入力: "9、#、#、1"
出力:false
関連トピックスタック
問題解決のアイデア
この質問の要件は、ツリーの事前順序付けの利便性を表す文字列を提供することであり、この文字列が二分木を形成できるかどうかを判断するために使用されます
- 既知の条件によれば、二分木の末端ノードには左右に2つの##文字が含まれている必要があると判断できるため、この数と2つの##を1つの#に置き換えることができます。
- これは排除され続け、最終的にルートノードは#になります。これは条件を満たしていると判断できます。画像も真実もありません。
コードデモ
class Solution {
public boolean isValidSerialization(String preorder) {
//用来存放各个节点的值,包括#这个符号
String[] strings = preorder.split(",");
while(!strings[0].equals("#" ))
{
//临时存放节点的值,包括#,主要目的是消除数字和##
Stack<String> sb=new Stack<>();
//存储上次更新节点的数量,包括#
int length1=strings.length;
//开始遍历,这一步为了就是消除数字,和两个连续的#
for(String s:strings)
{
//消除的条件
if(s.equals("#") && sb.peek().equals(s)) {
//如果当前值是#,栈顶元素也是#,这是不可能的,构成不了数,直接false
if(sb.get(0).equals("#"))
return false;
//移除元素
if(!sb.get(sb.size()-2).equals("#"))
{
sb.remove(sb.size()-2);
continue;
}
}
sb.add(s);
}
int length2=sb.size();
//当经过消除之后,节点的数量没有变化,那么,直接跳出
if(length1==length2)
{
break;
}
//用临时量更新strings数组的量
strings= sb.toArray(new String[sb.size()]);
}
//判断成树条件。
if(strings.length==1&&strings[0].equals("#"))
return true;
return false;
}
}
効果のデモンストレーション
情報の
回答は成功しました:
実行時間:11ミリ秒、Javaユーザーの5.77%を打ち負かしました
メモリ消費量:38.5 MB、Javaユーザーの49.85%を打ち負かしました