夜刷:平衡二叉樹的基本操作

Frankiehp發表於2020-12-17

在這裡插入圖片描述
在這裡插入圖片描述

思路:
用二叉樹維護一個滑動視窗
用最值來剪枝
主要涉及平衡二叉樹刪除 插入 查詢,沒有做平衡旋轉操作,這道題目的用例可能沒有考察這方面的效能

class Solution {
public:
	typedef struct NODE {
		struct NODE* left;
		struct NODE* right;
		int val;
		NODE(int _val) :left(NULL), right(NULL), val(_val) {
		}
	}NODE;

	NODE* head = NULL;
	int windowCount = 0;
	int max, min;

	void insertToTree(int x) {
		if (windowCount == 0) {
			min = x; max = x;
		}

		windowCount++;

		if (head == NULL) {
			head = new NODE(x);
			return;
		}

		NODE* p = head;

		while (p != NULL) {
			if (x > p->val) {
				if (NULL == p->right) {
					p->right = new NODE(x);
					break;
				}
				else {
					p = p->right;
				}
			}
			else {
				if (NULL == p->left) {
					p->left = new NODE(x);
					break;
				}
				else {
					p = p->left;
				}
			}
		}
	}

	void updateMax() {

		NODE* p = head;
		while (NULL != p) {
			max = p->val;
			p = p->right;
		}
	}

	void updateMin() {

		NODE* p = head;
		while (NULL != p) {
			min = p->val;
			p = p->left;
		}
	}

	void deleteFromTree(int x) {
		windowCount--;

		//find x
		NODE* p = head, *pre = NULL;
		while (NULL != p && p->val != x) {
			if (x > p->val) {
				pre = p;
				p = p->right;
			}
			else {
				pre = p;
				p = p->left;
			}
		}

		if (p == NULL) {
			return;
		}
		//leaf node ?
		if (p->right == NULL && p->left == NULL) {
			if (pre) {
				pre->left = pre->left == p ? NULL : pre->left;
				pre->right = pre->right == p ? NULL : pre->right;
			}
			else {
				head = NULL;
			}
			delete p;

		}
		else //have one child
			if (p->right == NULL || p->left == NULL) {
				if (pre) {
					pre->left = pre->left == p ? (p->right == NULL ? p->left : p->right) : pre->left;
					pre->right = pre->right == p ? (p->right == NULL ? p->left : p->right) : pre->right;
				}
				else {
					head = p->right == NULL ? p->left : p->right;
				}
				delete p;
			}
			else
			{
				//both child, i will exchange the right child's left chird
				NODE* q = p->right; pre = p;
				while (q->left != NULL) {
					pre = q;
					q = q->left;
				}
				int temp = p->val; p->val = q->val; q->val = temp;

				//if pre is q, we need update right chird or we need update left
				if (pre == p) {
					p->right = q->right;
					delete q;
				}
				else {
					pre->left = q->right;
					delete q;
				}
			}

	update:
		if (x == max) {
			updateMax();
		}
		if (x == min) {
			updateMin();
		}
	}

	bool find(int x, int t) {
		bool ret = false;
		NODE* p = head;

		while (p != NULL) {
            if (p->val == x) return true;
            
			if (x > p->val) {
				if (NULL == p->right) {
					break;
				}
				else {
					if (labs((long)x - (long)p->val) <= t) {
						ret = true;
						break;
					}
					p = p->right;
				}
			}
			else {
				if (NULL == p->left) {
					break;
				}
				else {
					if (labs((long)x - (long)p->val) <= t) {
						ret = true;
						break;
					}
					p = p->left;
				}
			}
		}

		return ret;
	}
	bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {

		int begin = 0;
		for (int i = 0; i < nums.size(); ++i) {

			if (windowCount >= k + 1) {
				deleteFromTree(nums[begin++]);
			}

			if (windowCount != 0) {
				if (labs((long)nums[i] - (long)min) <= t || labs((long)nums[i] - (long)max) <= t)
					return true;
				else {
					if (find(nums[i], t)) {
						return true;
					}
				}
			}

			insertToTree(nums[i]);

			max = nums[i] > max ? nums[i] : max;
			min = nums[i] < min ? nums[i] : min;
		}
		return false;
	}
};

相關文章