トピック:
【问题描述】输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。如果是返回true,否则返回false。
【输入形式】输入任意长度的数组,数字之间空格分开
【输出形式】true 或者 false
【样例输入】输入 5 7 6 9 11 10 8
【样例输出】true
【样例说明】由于这一整数序列是如下树的后序遍历结果:
8
/ \
6 10
/ \ / \
5 7 9 11
因此返回true。
【评分标准】暴力求解法不得分。
アイデア:
- この質問をしたときは振り返りませんでした。並べ替えで順番の構造が得られると思いました。フォローアップと順番でツリーを構築して判断できます。ツリーが二分探索木であるかどうか。しかし、この考えは間違っています
- 正しい考え方は実際には非常に単純です。
接尾辞の式を確認します。最後の式はルートです。ツリーを検索し、配列の先頭からルートよりも大きい最初のノードまで順番に配列をトラバースします。左の子です。右の子はすべてルートより大きくなければならず、再帰的です。右の子がルートより大きくない場合、接尾辞の走査は間違っています。
pre(int las[], int start, int index)
この関数は再帰関数です。start-indexはこの時点でトラバースされるサフィックス範囲です。indexはこの範囲のルートです。たとえば、5 7 6 9 11 10 8
先頭start = 0, index = 6
で、las [index]はこの範囲のルートです。
find_min(int las[], int start, int index)
この関数は、ルート以上の最初のノードを見つけ、このポイントを使用してスコープを分割します。基本的に、ルートの左右の子ノードを分割します。
- 最後に左右のサブ範囲への再帰
コード:
#include <stdio.h>
#include <stdlib.h>
int find_min(int las[], int start, int index) {
for (int i = start; i < index; i++) {
if (las[i] >= las[index]) {
return i;
}
}
}
int pre(int las[], int start, int index) {
if (start < index) {
int end = find_min(las, start, index);
for (int i = end; i < index; i++) {
if (las[i] < las[index]) {
return 0;
}
}
pre(las, start, end - 1);
pre(las, end, index - 1);
}
return 1;
}
int main() {
int las[40];
int l_num = 0;
do {
scanf("%d", &las[l_num++]);
} while (getchar() != '\n');
if (pre(las, 0, l_num - 1)) {
printf("true");
}
else
printf("false");
return 0;
}