寫在最前
因爲各種各樣的原因,要開始準備春招,所以開始刷劍指offer(第二版)。
題意
輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。
這個是個二叉樹很基礎的題啦,需要用遞歸來實現。主要講解在書的62頁,主要貼自己的代碼和自己的理解。
主要利用的規律如下圖:
代碼
//這裏我們遞歸開始之前傳入的是整個pre和in數組,然後在之後的遞歸中再改變pre和in的大小
struct TreeNode *test(int *pre_start, int *pre_end, int *in_start, int *in_end) {
//創建一個節點並malloc
struct TreeNode *root = (struct TreeNode *) malloc(sizeof(struct TreeNode));
//把這個節點賦值爲當前的pre的第一個數,因爲根據規律,這個數是根節點
root->val = *pre_start;
root->left = NULL;
root->right = NULL;
//如果首尾相等,說明到了遞歸最後的終止條件了,只有一個節點了,就返回這個節點
if (pre_end == pre_start)
return root;
//然後我們在中序遍歷的數組中要找到和前序遍歷根節點相等的節點,然後記下到這個節點的長度,這個長度就是左子樹的長度
//就是根據上圖找到左右子樹,然後再構建
int left_len = 0;
for (int i = 0; i <= (in_end - in_start); i++)
if (in_start[i] == root->val) {
left_len = i;
break;
}
//如果左子樹的長度大於0,就構建左子樹
if (left_len > 0)
root->left = test(pre_start + 1, pre_start + left_len, in_start, in_start + left_len - 1);
//右子樹大於0就構建右子樹
if (in_end - in_start >= left_len + 1)
root->right = test(pre_start + left_len + 1, pre_end, in_start + left_len + 1, in_end);
//最後返回構建的根節點
return root;
}
class Solution {
public:
//題目給的要求傳進來的參數是兩個vector,所以想要做遞歸,還需要改成數組形式纔可以
TreeNode *reConstructBinaryTree(vector<int> pre, vector<int> vin) {
//&pre[0]就是把vector直接變成數組。然後傳入到遞歸函數中
return test(&pre[0],&pre[0]+pre.size()-1,&vin[0],&vin[0]+vin.size()-1);
}
};