1. 程式人生 > >1043 Is It a Binary Search Tree (25 分)C++實現(已AC)

1043 Is It a Binary Search Tree (25 分)C++實現(已AC)

題目

題目連結 :https://pintia.cn/problem-sets/994805342720868352/problems/994805440976633856

思路:

建樹的思路是不可行的, 對於普通二叉樹一定需要中序遍歷和另一個遍歷來複原,對於二叉搜尋樹來說, 即使有一些規則限制, 通過一個前序遍歷序列, 不能判斷在只有一側樹時的情況. 引起的問題:

  1. 判斷映象還是原始二叉搜尋樹後, 需要保持其一致性, 不能該節點按照原始二叉樹規則排列, 但其子樹按照映象二叉搜尋樹進行排列
  2. 當只有一側子樹存在時無法判斷這是二叉搜尋樹還是其映象.
  3. 由1,2兩點, 當映象搜尋樹的非葉節點層出現一側存在樹的情況, 會造成無法判斷的情況.2. 當只有一側子樹存在時無法判斷這是二叉搜尋樹還是其映象. 3. 由1,2兩點, 當映象搜尋樹的非葉節點層出現一側存在樹的情況, 會造成無法判斷的情況.3. 由1,2兩點, 當映象搜尋樹的非葉節點層出現一側存在樹的情況, 會造成無法判斷的情況.2. 當只有一側子樹存在時無法判斷這是二叉搜尋樹還是其映象. 3. 由1,2兩點, 當映象搜尋樹的非葉節點層出現一側存在樹的情況, 會造成無法判斷的情況.
   8
    \
     6
    / \
   7   5

這種情況, 在建樹時, 非常難以解決, 除非寫規則在遇到單側二叉樹時, 不判斷其映象關係, 這會讓程式碼變得非常複雜

通過柳神的程式碼的點撥, 可以考慮直接由前序遍歷序列按照原始二叉搜尋樹的規則得出其後序遍歷, 如果結果小於N, 嘗試用mirror規則去得出其後續遍歷, 如果結果依然小於N, 則說明不是二者.

測試點:

// 題目給出的測試點

7
8 6 5 7 10 8 11

// 題目給出的測試點

7
8 10 11 8 6 7 5

// 題目給出的測試點

7
8 6 8 5 10 9 11

// 單側子樹, 原始二叉搜尋樹

4
8 6 5 7

// 單側子樹, 映象二叉搜尋樹

4
8 6 7 5

// 上層是映象,下層是原始, 對應最後一個測試點

7
8 10 8 11 6 7 5
expect: NO

// 增序

3
3 2 1

//降序

3
1 2 3

#include<iostream>
#include<vector>
using namespace std;

vector<int> pre, post;
bool is_mirror =
false; void build_origin(int front, int tail) { if (front > tail) return ; else { int i = front+1, j = tail; if (!is_mirror) { while (i <= tail && pre[front] > pre[i]) i++; while (j > front && pre[front] <= pre[j]) j--; } else { while (i <= tail && pre[front] <= pre[i]) i++; while (j > front && pre[front] > pre[j]) j--; } if (i - j != 1) return ; // 這裡i, j剛好交錯一次 build_origin(front + 1, i - 1); build_origin(j + 1, tail); post.push_back(pre[front]); } } int main() { int N; cin >> N; pre.resize(N); for(int i = 0; i < N; i++) { cin >> pre[i]; } build_origin(0, N-1); if (post.size() < N) { post.clear(); is_mirror = true; build_origin(0, N-1); } if (post.size() != N) printf("NO\n"); else { printf("YES\n"); printf("%d", post[0]); for (int i = 1; i < N; i++) printf(" %d", post[i]); } return 0; }