剑指 Offer 33. 二叉搜索树的后序遍历序列
题目:
思路:
没有考虑全面导致
1.多次提交失败,每次都拿失败的用例去改。。。
2.虽然提交通过,但是代码逻辑混乱,思路不变,代码可以优化
思路:后续遍历序列最后一个必是根节点,从始至终,比其小的为左子树,比其大的为右子树。
假设k为临界值,那么k之后的元素都必须比root大,否则返回false。最后reture 前 && 后 即可
(其实还有,都比根节点小和都比根节点大的情况,这两者直接return length-1即可)
题解:
class Solution {
public boolean verifyPostorder(int[] postorder) {
return verify(postorder, 0, postorder.length);
}
private boolean verify(int[] postorder, int i, int j) {
int length = j - i;
if (length <= 2) {
return true;
}
// 1、只有右子树
int root = postorder[j - 1];
int a = -1;
for (int k = i; k < j; k++) {
if (postorder[k] > root) {
a = k;
break;
}
}
for (int k = a; a!=-1 && k < j; k++) {
if (postorder[k] < root) {
return false;
}
if (k == j - 1) {
return verify(postorder,i,j-1);
}
}
// 2、只有左子树
for (int k = i; k < j; k++) {
if (postorder[k] < root) {
continue;
}
if (k == j - 1) {
return verify(postorder, i, j-1);
}
}
// 3、先左子树,后右子树
int temp = -1;
for (int k = i; k < j; k++) {
if (postorder[k] < root && postorder[k + 1] > root) {
temp = k;
break;
}
}
if (temp >= i && temp <= j) {
for (int k = temp + 1; k < j; k++) {
// 如果都确定都是右子树了,中间又突然来个左子树节点,那么肯定是错误的
if (postorder[k] < root) {
return false;
}
}
return verify(postorder, i, temp + 1) && verify(postorder, temp + 1, j-1);
}
// 必须的一个reture
return false;
}
}
优化后的代码:
class Solution {
public boolean verifyPostorder(int[] postorder) {
return verify(postorder, 0, postorder.length);
}
private boolean verify(int[] postorder, int i, int j) {
// 如果只有两个值,那么就没有比较的必要了,直接返回ture
if (j - i <= 2) {
return true;
}
int root = postorder[j - 1];
// 标识位
int temp = -1;
for (int k = i; k < j; k++) {
if (postorder[k] > root) {
temp = k;
break;
}
}
if (temp != -1) {
for (int k = temp; k < j; k++) {
if (postorder[k] < root) {
return false;
}
}
return verify(postorder, i, temp) && verify(postorder, temp, j-1);
} else {
return verify(postorder, i, j - 1);
}
}
}