---
# System prepended metadata

title: 13. Binary Search Tree
tags: [LeetCode筆記]

---

# Binary Search Tree

###### tags: `LeetCode筆記`

![](https://i.imgur.com/KiSjINf.png)

It is noteworthy that **inorder traversal** in BST will be in **ascending order**.
Therefore, the inorder traversal is the most frequent used traversal method of a BST.

## :memo: 一、Basic Operation
### 1. Search
#### recursion1:
```
TreeNode* searchBST(TreeNode* root, int target) {
        if (!root || root->val == target) {
            return root;
        }
        if (target < root->val) {
            return searchBST(root->left, target);
        }
        return searchBST(root->right, target);
    }
```
#### recursion2:
```
class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        if (root == nullptr) {
            return nullptr;
        }
        
        if (val < root->val) {
            return searchBST(root->left, val);
        }
        else if (val > root->val) {
            return searchBST(root->right, val);
        }
        else {
            return root;
        }
        
        return nullptr;
    }
};
```
#### iteration:
```
TreeNode searchBST(TreeNode root, int target) {
        TreeNode cur = root;
        while (cur != null && cur.val != target) {
            if (target < cur.val) {
                cur = cur.left;
            } else {
                cur = cur.right;
            }
        }
        return cur;
    }
```

### 2. Insertion
#### C
```
struct TreeNode* CreateTreeNode(int val)
{
    struct TreeNode* newnode = (struct TreeNode*) malloc(sizeof(struct TreeNode));
    newnode->val = val;
    newnode->left = NULL;
    newnode->right = NULL;
    
    return newnode;
}

void insert(struct TreeNode* root, int val)
{
    
    if (val <= root->val)
    {
        if (root->left != NULL)
        {
            insert(root->left, val);
        }
        else
        {
            root->left = CreateTreeNode(val);
        }
    }
    else
    {
        if (root->right != NULL)
        {
            insert(root->right, val);
        }
        else
        {
            root->right = CreateTreeNode(val);
        }
    }
    
}

struct TreeNode* insertIntoBST(struct TreeNode* root, int val) 
{
    if (root==NULL)
    {
        root = CreateTreeNode(val);
        
        return root;
    }
    
    insert(root,val);
    
    return root;
}
```
#### C++
```
class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if (root == nullptr) {
            TreeNode* newnode = new TreeNode(val);
            return newnode;
        }
        
        if (val < root->val) {
            root->left = insertIntoBST(root->left, val);
        }
        else if (val > root->val) {
            root->right = insertIntoBST(root->right, val);
        }
        
        return root;
    }
};
```

### 3. Deletion
![](https://i.imgur.com/xre6wPH.png)
#### C
```
int successor(struct TreeNode* root)
{
    root = root->right;
    while (root->left != NULL)
    {
        root = root->left;
    }
    
    return root->val;
}

int predecessor(struct TreeNode* root)
{
    root = root->left;
    while (root->right != NULL)
    {
        root = root->right;
    }
    
    return root->val;
}

struct TreeNode* deleteNode(struct TreeNode* root, int key)
{
    if (root == NULL)
    {
        return NULL;
    }
    
    if (key > root->val)
    {
        root->right = deleteNode(root->right, key);
    }
    else if(key < root->val)
    {
        root->left = deleteNode(root->left, key);
    }
    else
    {
        if (root->left == NULL && root->right == NULL)
        {
            root = NULL;
        }
        else if (root->right != NULL)
        {
            root->val = successor(root);
            root->right = deleteNode(root->right, root->val);
        }
        else
        {
            root->val = predecessor(root);
            root->left = deleteNode(root->left, root->val);
        }
    }
    
    return root;
}
```
#### C++
```
class Solution {
private:
    TreeNode* findSuccessor(TreeNode* root) {
        TreeNode* cur = root->right;
        while (cur && cur->left) {
            cur = cur->left;
        }
        
        return cur;
    }
    
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (!root) {
            return nullptr;
        }
        
        if (root->val == key) {
            if (!root->left) {
                return root->right;
            }
            
            if (!root->right) {
                return root->left;
            }
            
            TreeNode* p = findSuccessor(root);
            root->val = p->val;
            root->right = deleteNode(root->right, p->val);
            return root;
        }
        
        if (root->val < key) {
            root->right = deleteNode(root->right, key);
        }
        else {
            root->left = deleteNode(root->left, key);
        }
        
        return root;
    }
};
```

## :memo: *Validate Binary Search Tree (Medium)
![](https://i.imgur.com/ooz78YQ.png)

![](https://i.imgur.com/I8hPUUf.png)

### 作法 recursion
宣告一個private TreeNode* prev去紀錄上一個root，因此只要root->val<=prev->val，就是false
```
class Solution {
private:
    TreeNode* prev = nullptr;
public:
    bool isValidBST(TreeNode* root) {
        if (root == nullptr) {
            return true;
        }
        
        if (!isValidBST(root->left)) {
            return false;    
        }
        
        if (prev != nullptr && root->val <= prev->val) {
            return false;
        }
        
        prev = root;
        
        return isValidBST(root->right);
    }
};
```

### 作法 iteration
```
class Solution {
public:
    bool isValidBST(TreeNode* root) {
        stack<TreeNode*> stk;
        TreeNode* prev = nullptr;

        while (!stk.empty() or root != nullptr) {
            while (root != nullptr) {
                stk.push(root);
                root = root->left;
            }
            root = stk.top();
            stk.pop();

            if (prev != nullptr and root->val <= prev->val) {
                return false;
            }
            prev = root;
            root = root->right;
        }

        return true;
    }
};
```

## :memo: *Inorder Successor in BST (Medium)
![](https://i.imgur.com/fnIJUm3.png)

![](https://i.imgur.com/Snhczgu.png)

### 作法1
利用flag去判斷找到p，然後往下traverse後的第一個就是successor，assign給q後，flag=0，並且return，但是會繼續traverse所以慢

### 作法2
利用BST的特性，比較p和root的值，然後用一個變數successor去紀錄(當p的值>root的值)會往左(先successor=root再root=root->left)
```
class Solution {
public:
    TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
        TreeNode* successor = nullptr;
        
        while (root != nullptr) {
            if (p->val >= root->val) {
                root = root->right;
            }
            else {
                successor = root;
                root = root->left;
            }
        }
        
        return successor;
    }
};
```

## :memo: Binary Search Tree Iterator (Medium)
![](https://i.imgur.com/x9LJOyk.png)

![](https://i.imgur.com/uh8IHyo.png)

### 作法 C
建一個global struct的變數list去存，然後traverse函數中的是雙指標obj去跑next，回傳值都是看list那一個
```
typedef struct {
    int val;
    struct BSTIterator* next;
}BSTIterator;

BSTIterator* list;

void traverse(BSTIterator** obj, struct TreeNode* root) {
    if (root == NULL)
    {
        return;
    }
    
    if (root->left)
    {
        traverse(obj, root->left);
    }

    BSTIterator* newnode = (BSTIterator*) malloc(sizeof(BSTIterator));
    newnode->val = root->val;
    newnode->next = NULL;
    
    (*obj)->next = newnode;
    (*obj) = (*obj)->next;
    
    // printf("%d\n", (*obj)->val);
    
    if (root->right)
    {
        traverse(obj, root->right);
    }
}

BSTIterator* bSTIteratorCreate(struct TreeNode* root) {
    BSTIterator* head = (BSTIterator*) malloc(sizeof(BSTIterator));
    head->val = 0;
    head->next = NULL;
    
    BSTIterator* p;
    p = head;
    
    traverse(&head, root);
    
    list = p;
    
    return p;
}

int bSTIteratorNext(BSTIterator* obj) {  
    list = list->next;
    
    return list->val;
}

bool bSTIteratorHasNext(BSTIterator* obj) {
    if (list->next)
    {
        return true;
    }
    
    return false;
}

void bSTIteratorFree(BSTIterator* obj) {
    BSTIterator* p;
    
    while (obj != NULL)
    {
        p = obj;
        obj = obj->next;
        free(p);
    }
}
```

### 作法 C++
大while包住(用stack跑小while一直往左子樹後root=root->right)
```
class BSTIterator {
private:
    vector<int> list;
    int index = 0;
    
public:
    BSTIterator(TreeNode* root) {
        stack<TreeNode*> s;
        TreeNode* prev = nullptr;
        
        while (!s.empty() or root != nullptr) {

            while (root != nullptr) {
                s.push(root);
                root = root->left;
            }
            
            root = s.top();
            s.pop();
            
            list.push_back(root->val);
                        
            root = root->right;
            
        }
        
    }
    
    int next() {
        if (index < list.size()) {
            return list[index++];    
        }
        
        return 0;
    }
    
    bool hasNext() {
        if (index >= list.size()) {
            return false;    
        }
        
        return true;
    }
};
```

## :memo: Kth Largest Element in a Stream (Easy)
![](https://i.imgur.com/vxtmcUg.png)

### 作法
```
struct Node {
    Node* left;
    Node* right;
    int val;
    int cnt;
    Node(int v, int c) : left(NULL), right(NULL), val(v), cnt(c) {}
};

class KthLargest {
private:
    Node* insertNode(Node* root, int num) {
        if (!root) {
            return new Node(num, 1);	    // return a new node if root is null
        }
        if (root->val < num) {			// insert to the right subtree if val > root->val
            root->right = insertNode(root->right, num);
        } else {						// insert to the left subtree if val <= root->val
            root->left = insertNode(root->left, num);
        }
        root->cnt++;
        return root;
    }
    int searchKth(Node* root, int k) {
        // m = the size of right subtree
        int m = root->right ? (root->right)->cnt : 0;
        // root is the m+1 largest node in the BST
        if (k == m + 1) {
            return root->val;
        }
        if (k <= m) {
            // find kth largest in the right subtree
            return searchKth(root->right, k);
        } else {
            // find (k-m-1)th largest in the left subtree
            return searchKth(root->left, k - m - 1);
        }
    }
    Node* root;
    int m_k;
public:
    KthLargest(int k, vector<int> nums) {
        root = NULL;
        for (int i = 0; i < nums.size(); ++i) {
            root = insertNode(root, nums[i]);
        }
        m_k = k;
    }
    
    int add(int val) {
        root = insertNode(root, val);
        return searchKth(root, m_k);
    }
};

/**
 * Your KthLargest object will be instantiated and called as such:
 * KthLargest obj = new KthLargest(k, nums);
 * int param_1 = obj.add(val);
 */
```

## :memo: *Lowest Common Ancestor of a Binary Search Tree (Medium)
![](https://i.imgur.com/GRPWSBz.png)

![](https://i.imgur.com/rgXYSOs.png)

### 作法
這題因為是BST，所以可以利用val去找共同祖先，不過一般的Binary Tree就不行了
```
struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q) {
    if (p->val > root->val && q->val > root->val)
    {
        return lowestCommonAncestor(root->right, p, q);
    }
    else if (p->val < root->val && q->val < root->val)
    {
        return lowestCommonAncestor(root->left, p, q);
    }
    else
    {
        return root;
    }
}
```

## :memo: Contains Duplicate III (Hard)
Given an integer array nums and two integers k and t, return true if there are two distinct indices i and j in the array such that abs(nums[i] - nums[j]) <= t and abs(i - j) <= k.

### 作法
很簡單的想法寫成程式碼就好，要注意的是要改成long long t，先排序後再暴力解
```
void swap(int *p, int *q)
{
    int t = *p; 
    *p = *q;
    *q = t;
}

void sort(int* nums, int* indexes, int low, int high)
{
    int l = low, h = high;
    int v = nums[l + (h - l) / 2];
    while (l <= h)
    {
        while(nums[l] < v) l++;
        while(nums[h] > v) h--;
        if (l <= h)
        {
            swap(nums + l, nums + h);
            swap(indexes + l, indexes + h);
            l++, h--;
        }
    }
    if(h > low)
        sort(nums, indexes, low, h);
    if(l < high)
        sort(nums, indexes, l, high);
}

bool containsNearbyAlmostDuplicate(int* nums, int numsSize, int k, long long t) {
    int* indexes = (int*) malloc(sizeof(int) * numsSize);
    for (int i = 0; i < numsSize; i++)
    {
        indexes[i] = i;
    }
    
    sort(nums, indexes, 0, numsSize - 1);
    
    for (int i = 0; i < numsSize; i++)
    {
        long long top = nums[i] + t;
        for (int j = i + 1; j < numsSize && nums[j] <= top; j++)
        {
            if (abs(indexes[i] - indexes[j]) <= k)
            {
                return true;
            }
        }
    }
    
    return false;
}
```

### 作法 Bucket
```
class Solution {
public:
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, long t) {
        if (nums.size() < 2 || t < 0 || k < 0) return false;
        int minx = INT_MAX, maxx = INT_MIN;
        //find the minimum and maximum to determine the number of buckets
        for (auto & i : nums) {
            minx = min(minx, i);
            maxx = max(maxx, i);
        }
        int n = ((long)maxx - (long)minx) / (t + 1) + 1;
        //initialize by -(k + 1)
        vector<int> buckets(n, -(k + 1));
        for (int i = 0, j; i < nums.size(); i++) {
            //get the index of bucket
            j = ((long)nums[i] - (long)minx) / (t + 1);
            //check the two constraints
            if ((i - buckets[j] <= k) || (j && i - buckets[j - 1] <= k && (long)nums[i] - (long)nums[buckets[j - 1]] <= t) || (j < n - 1 && i - buckets[j + 1] <= k && (long)nums[buckets[j + 1]] - (long)nums[i] <= t))
                return true;
            buckets[j] = i;
        }
        return false;
    }
};
```

### 作法 Binary Search Tree
```
class Solution {
public:
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int indexDiff, int valueDiff) {
        if (nums.size() == 0) {
            return false;
        }
        
        if (indexDiff == 0) {
            return false;
        }
        
        multiset<int> bst;
        
        for (int i = 0; i < nums.size(); i++) {
            const auto it = bst.lower_bound(nums[i] - valueDiff);
            if (it != bst.end() and abs(*it - nums[i]) <= valueDiff) {
                return true;
            }
            
            bst.insert(nums[i]);
            
            if (bst.size() > indexDiff) {
                bst.erase(bst.find(nums[i - indexDiff]));
            }
        }
        
        return false;
    }
};
```

## :memo: 二、Height-Balanced BST
參考網址:
https://leetcode.com/explore/learn/card/introduction-to-data-structure-binary-search-tree/143/appendix-height-balanced-bst/1021/

## :memo: *Balanced Binary Tree (Easy)
a binary tree in which the left and right subtrees of every node differ in height by no more than 1.

### 作法
計算左子樹與右子樹高度差是否<2，然後往左往右遞迴，並且去&&3個結果
```
int height(struct TreeNode* root) {
    if (root == NULL)
    {
        return -1;
    }
    
    return 1 + fmax(height(root->left), height(root->right));
}

bool isBalanced(struct TreeNode* root) {
    if (root == NULL)
    {
        return true;
    }
    
    return abs(height(root->left) - height(root->right)) < 2 && isBalanced(root->left)  && isBalanced(root->right);
}
```

### 作法 最快code
```
class Solution {
public:
    pair<bool,int> isBlanced(TreeNode* root) {
        if(root==NULL) {
            pair<bool,int>p = make_pair(true,0);
            return p;
        }

        pair<bool,int>left = isBlanced(root->left);
        pair<bool,int>right = isBlanced(root->right);


        bool leftans = left.first;
        bool rightans = right.first;
        bool diff = abs(left.second - right.second) <= 1;

        pair<bool,int>ans;
        ans.second = max(left.second, right.second) + 1;

        if (leftans && rightans && diff ) {
            ans.first = true;
        }
        else {
            ans.first = false;
        }
        return ans;
    }

    bool isBalanced(TreeNode* root) {
        return isBlanced(root).first;
    }
};
```

## :memo: Convert Sorted Array to Binary Search Tree (Easy)
把排序過的陣列轉成BST

### 作法 C
陣列分成左半右半去建root，一直向左向右遞迴
```
struct TreeNode* createTreeNode(int val)
{
    struct TreeNode* newnode = (struct TreeNode*) malloc(sizeof(struct TreeNode));
    newnode->val = val;
    newnode->left = NULL;
    newnode->right = NULL;
    
    return newnode;    
}

struct TreeNode* helper(int* nums, int left, int right)
{
    if (left > right)
    {
        return NULL; 
    }
    
    int p = (left + right) / 2;
    
    struct TreeNode* root = createTreeNode(nums[p]);
    root->left = helper(nums, left, p - 1);
    root->right = helper(nums, p + 1, right);
    
    return root;
}
struct TreeNode* sortedArrayToBST(int* nums, int numsSize)
{
    return helper(nums, 0, numsSize - 1);
}
``` 

### 做法 C++
```
class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        if (nums.size() == 0) {
            return nullptr;
        }
        if (nums.size() == 1) {
            return new TreeNode(nums[0]);
        }
        
        int middle = nums.size() / 2;
        TreeNode* root = new TreeNode(nums[middle]);
        
        vector<int> leftInts(nums.begin(), nums.begin() + middle);
        vector<int> rightInts(nums.begin() + middle + 1, nums.end());
        
        root->left = sortedArrayToBST(leftInts);
        root->right = sortedArrayToBST(rightInts);
        
        return root;
    }
};
```

## :memo: 刷題檢討
二元搜尋樹的問題偏簡單，要利用到數值與數值之間的關係，基本的搜尋新增很容易，**刪除有點複雜，要去多弄熟，可以和二元樹一起複習**