手撕红黑树

红黑树的平衡条件

  1. 每个节点非黑即红
  2. 根节点是黑色
  3. 叶节点(NIL即虚拟空节点)是黑色
  4. 如果一个节点是红色,则它的两个子节点都是黑色的
  5. 从根节点出发到所有叶节点路径上,黑色节点数量相同

问题1: 红黑树中最长路径和最短路径的关系是什么?

根据平衡条件第四、五点, 最短路径都是黑色,最长路径都是红色,最长是最短的两倍

问题2:怎么理解条件3中的NIL节点

就像文章中的标点符号,虽然它不属于内容的部分,平时也不会主意它,可要是真没有,就会很麻烦

问题3:新插入的节点是什么颜色?红色?黑色?

红色,因为插入黑色一定引发失衡,插入红色不一定引发失衡,一个必死,一个有概率活,正常人,都会选择后者

平衡调整终极法门

  • 插入调整站在祖父节点看
  • 删除调整站在父节点看
  • 插入和删除的情况处理一共五种

插入情况

调整之前路径上的黑节点,数量等于调整之后黑节点数量

代码实现

#define NIL &(node::__NIL)
struct node {
	node(int key = 0, int color = 0, node *lchild = NIL, node *rchild = NIL) : key(key), color(color), lchild(lchild), rchild(rchild) {}
	int key;
	int color; // 0 red, 1 black, 2 double black
	node *lchild, *rchild;
	static node __NIL;
}

node __NIL(0, 1);

node *getNewNode(int key){
	return new node(key);
}

bool has_red_child(node *root){
	return root->lchild->color == 0 || root->rchild->color == 0;
}

node *left_rotate(node *root){
	node *temp = root->rchild;
	root->rchild = temp->lchild;
	temp->lchild = root;
	return temp;
}

node *right_rotate(node *root){
	node *temp = root->lchild;
	root->lchild = temp->rchild;
	temp->rchild = root;
	return temp;
}

node *insert_maintain(node *root){
	bool flag = 0;
	if(root->lchild->color == 0 && has_red_child(root->lchild)) flag = 1;
	else(root->rchild->color == 0 && has_red_child(root->right)) flag = 2;
	if(flag == 0) return root;
	if(root->lchild->color == 0 && root->rchild->color == 0){
		root->color = 0;
		root->lchild->color = root->rchild->color = 1;
		return root;
	}
	if(flag == 1){
		if(root->lchild->rchild->color == 0){
			root->lchild = left_rotate(root->lchild);
		}
		root = right_rotate(root);
	} else {
		if(root->rchild->lchild->color == 0){
			root->rchild = right_rotate(root->rchild);
		}
		root->left_rotate(root);
	}
	root->color = 0;
	root->lchild->color = root->rchild->color = 1;
}

node *__insert(node *root, int key){
	if(root == NIL) return getNewNode(key);
	if(key == root->key) return root;
	if(key < root->key){
		root->lchild = __insert(root->lchild, key);
	}else{
		root->rchild = __insert(root->rchild, key);
	}
	return insert_maintain(root);
}

node *insert(node *root, int key){
	root = __insert(root, key);
	root->color = 1;
	return root;
}

node *predecessor(node *root){
	node *temp = root->lchild;
	while(temp->rchild != NIL) temp = temp->rchild;
	return temp;
}

node *erase_maintain(node *root){
	if(root->lchild->color != 2 && root->rchild->color != 2) return root;
	int flag = 9;
	if(has_red_child(root)){
		root->color = 0;
		if(root->lchild->color == 0){
			root = right_rotate(root); flag = 1;
		} else {
			root = left_rotate(root); flag = 2;
		}
		root->color = 1;
		if(flag == 1) root->rchild = erase_maintain(root->rchild);
		else root->lchild = erase_maintain(root->lchild);
		return root;
	}
	if((root->lchild->color == 1 && !has_red_child(root->lchild))
	|| ((root->rchild->color == 1 && !has_red_child(root->rchild)){
		root->lchild->color -= 1;
		root->rchild->color -= 1;
		root->color += 1;
		return root;
	}
	if(root->lchild->color == 1){
		root->rchild->color = 1;
		if(root->lchild->lchild->color != 0){
			root->lchild->color = 0;
			root->lchild = left_rotate(root->lchild);
			root->lchild->color = 1;
		}
		root->lchild->color = root->color;
		root = right_rotate(root);
	} else {
		root->lchild->color = 1;
		if(root->rchild->rchild->color != 0){
			root->rchild->color = 0;
			root->rchild = left_rotate(root->lchild);
			root->rchild->color = 1;
		}
		root->rchild->color = root->color;
		root = left_rotate(root);
	}
	root->lchild->color = root->rchild->color = 1;
	return root;
}

node *__erase(node *root, int key){
	if(root == NIL) return Root;
	if(key < root->key){
		root->lchild = __erase(root->lchild, key);
	}else if(key > root->key){
		root->rchild = __erase(root->rchild, key);
	}else {
		if(root->lchild == NIL || root->rchild == NIL){
			node *temp = root->lchild == NIL ? root->rchild : root->lchild;
			temp->color = root->color;
			delete root;
			return temp;
		} else {
			node *temp = predecessor(root);
			root->key = temp->key;
			root->lchild = __erase(root->lchild, temp->key);
		}
	}
	return erase_maintain(root);
}

node *erase(node *root, int key){
	root = __erase(root, key);
	root->color = 1;
	return root;
}

void clear(node *root){
	if(root == NIL) return;
	clear(root->lchild);
	clear(root->rchild);
	delete root;
	return;
}

int main(){
	
	return 0;
}

题解

1339. 分裂二叉树的最大乘积

class Solution {
public:
    int avg, ans = 0;
    int getTotal(TreeNode *root){
        if(root == nullptr) return 0;
        int val =  root->val + getTotal(root->left) + getTotal(root->right);
        if(abs(val - avg) < abs(ans - avg)) ans = val;
        return val;
    }
    int maxProduct(TreeNode* root) {
        int total = getTotal(root);
        avg = total / 2;
        ans = total;
        getTotal(root);
        return (long long)ans * (total - ans) % (long long)(1e9+7);
    }
};

971. 翻转二叉树以匹配先序遍历

class Solution {
public:
    int ind;
    bool preorder(TreeNode *root, vector<int> &voyage, vector<int> &ret){
        if(root == nullptr) return true;
        if(voyage[ind] != root->val){
            ret.clear();
            ret.push_back(-1);
            return false;
        }
        ind += 1;
        if(ind + 1 == voyage.size()) return true;
        if(root->left && root->left->val != voyage[ind]){
            swap(root->left, root->right);
            ret.push_back(root->val);
        }
        if(!preorder(root->left, voyage, ret)) return false;
        if(!preorder(root->right, voyage, ret)) return false;
        return true;

    }
    vector<int> flipMatchVoyage(TreeNode* root, vector<int>& voyage) {
       vector<int> ret;
       ind = 0;
       preorder(root, voyage, ret); 
       return ret;
    }
};

117. 填充每个节点的下一个右侧节点指针 II

class Solution {
public:
    Node *layer_connect(Node *head){
       Node *p =  head, *pre = nullptr, *new_head = nullptr;
       while(p){
            if(p->left){
                if(pre) pre->next = p->left;
                pre = p->left;
            }
            if(new_head == nullptr && pre) new_head = pre;
            if(p->right){
                if(pre) pre->next = p->right;
                pre = p->right;
            }
            if(new_head == nullptr) new_head = pre;
            p = p->next;
       }
       return new_head;
    }

    Node* connect(Node* root) {
        Node *p = root;
        while(p = layer_connect(p));
        return root;
    }
};

LCR 053. 二叉搜索树中的中序后继

class Solution {
public:
    TreeNode *pre, *ans;
    bool inorder(TreeNode *root, TreeNode *p){
        if(root == nullptr) return false;
        if(inorder(root->left, p)) return true;
        if(pre == p){
            ans = root;
            return true;
        }
        pre = root;
        if(inorder(root->right, p)) return true;
        return false;
    }
    TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
        pre = ans = nullptr;
        inorder(root, p);
        return ans;
    }
};

449. 序列化和反序列化二叉搜索树

class Codec {
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        if(root == nullptr) return "";
        string ret = "";
        stringstream ss;
        ss << root->val;
        ss >> ret;
        if(root->left == nullptr && root->right == nullptr) return ret;
        ret += "(";
        ret += serialize(root->left);
        if(root->right){
            ret += ",";
            ret += serialize(root->right);
        }
        ret += ")";
        return ret;
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        int scode = 0, ind = 0, k = 0;
        stack<TreeNode *> s;
        TreeNode *p, *root = nullptr;
        while(ind < data.size()){
            switch(scode){
                case 0: {
                    if(data[ind] <= '9' && data[ind] >= '0') scode = 1;
                    else if(data[ind] == '(') scode = 2;
                    else if(data[ind] == ',') scode = 3;
                    else if(data[ind] == ')') scode = 4;
                } break;
                case 1: {
                    int num = 0;
                    while(ind < data.size() && data[ind] <= '9' && data[ind] >= '0'){
                        num = num *10 + (data[ind] - '0');
                        ind += 1;
                    }
                    p = new TreeNode(num);
                    if(root == nullptr) root = p;
                    if(k == 1) s.top()->left = p;
                    else if(k == 2) s.top()->right = p;
                    scode = 0;
                } break;
                case 2: {
                    s.push(p);
                    ind += 1;
                    k = 1;
                    scode = 0;
                } break;
                case 3: {
                    k = 2;
                    ind += 1;
                    scode = 0;
                } break;
                case 4: {
                    s.pop();
                    ind += 1;
                    scode = 0;
                } break;
            }
        }
        return root;
    }
};

78. 子集

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        int n = nums.size();
        vector<vector<int>> ret;
        for(int i = 0, I = (1 << n); i < I; i++){
            vector<int> arr;
            for(int j = 0; j < n; j++){
                if(i & (1 << j)) arr.push_back(nums[j]);
            }
            ret.push_back(arr);
        }
        return ret;
    }
};

47. 全排列 II

class Solution {
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        vector<vector<int>> ret;
        do{
            ret.push_back(nums);
        }while(next_permutation(nums.begin(), nums.end()));
        return ret;
    }
};

20. 存在重复元素 III

class Solution {
public:
    void delNum(map<long long, int> &h, long long x){
        h[x] -= 1;
        if(h[x] == 0) h.erase(h.find(x));
        return ;
    }
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int indexDiff, int valueDiff) {
        map<long long, int> h;
        for(int i = 0; i < nums.size(); i++){
            if(i > indexDiff){
                delNum(h, nums[i - indexDiff - 1]);
            }
            h[(long long)(nums[i]) - valueDiff - 1] += 1;
            h[(long long)(nums[i]) + valueDiff + 1] += 1;
            auto iter = h.find((long long)(nums[i]) - valueDiff - 1);
            iter++;
            if(iter->first != (long long)(nums[i]) + valueDiff + 1) return true;
            delNum(h, (long long)(nums[i]) - valueDiff - 1);
            delNum(h, (long long)(nums[i]) + valueDiff + 1);
            h[nums[i]] += 1;
        }
        return false;
    }
};

41. 缺失的第一个正数

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        for(int i = 0; i < nums.size(); i++){
            while(nums[i] != i + 1){
                if(nums[i] <= 0 || nums[i] > nums.size()) break;
                int ind = nums[i] - 1;
                if(nums[i] == nums[ind]) break;
                swap(nums[i], nums[ind]);
            }
        }
        int ind = 0;
        while(ind < nums.size() && nums[ind] == ind + 1) ++ind;
        return ind + 1;
    }
};

99. 恢复二叉搜索树

class Solution {
public:
    TreeNode *pre, *p, *q;
    void inorder(TreeNode *root){
         if(root == nullptr) return ;
        inorder(root->left);
        if(pre && root->val < pre->val) {
            if(p == nullptr) p = pre;
            q = root;
        }
        pre = root;
        inorder(root->right);
        return ;
    }
    void recoverTree(TreeNode* root) {
       pre = p = q = nullptr;
       inorder(root);
       swap(p->val, q->val);
       return ;
    }
};

653. 两数之和 IV - 输入二叉搜索树

class Solution {
public:
    void inorder(TreeNode *root, vector<int> &ret){
        if(root == nullptr) return;
        inorder(root->left, ret);
        ret.push_back(root->val);
        inorder(root->right, ret);
        return;
    }
    bool findTarget(TreeNode* root, int k) {
        vector<int> ret;
        inorder(root, ret);
        int p = 0, q = ret.size() - 1;
        while(p < q && ret[p] + ret[q] - k){
            if(ret[p] + ret[q] < k){
                p += 1;
            }else{
                q -= 1;
            }
        }
        return p < q;
    }
};

204. 计数质数

class Solution {
public:
    int countPrimes(int n) {
        int *prime = new int[n + 1];
        for(int i = 0; i < n; i++) prime[i] = 0;
        for(int i = 2; i * i < n; i++){
            if(prime[i]) continue;
            for(int j = 2 * i; j < n; j += i){
                prime[j] = 1;
            }
        }
        int cnt = 0;
        for(int i = 2; i < n; i++) cnt += (prime[i] == 0);
        delete[] prime;
        return cnt;
    }
};

504. 七进制数

class Solution {
public:
    string convertToBase7(int num) {
        if(num == 0) return "0";
        int flag = (num < 0);
        string s = "";
        while(num){
            s += char(abs(num % 7) + '0');
            num /= 7;
        }
        if(flag) s += "-";
        reverse(s.begin(), s.end());
        return s;
    }
};

461. 汉明距离

class Solution {
public:
    int hammingDistance(int x, int y) {
        x ^= y;
        int cnt = 0;
        while(x){
            x &= (x - 1);
            cnt += 1;
        }
        return cnt;
    }
};

528. 按权重随机选择

class Solution {
public:
    int n;
    vector<int> sum;
    Solution(vector<int>& w) :sum(w){
        for(int i = 1; i < sum.size(); i++) sum[i] += sum[i - 1];
        n = sum[sum.size() - 1];
    }
    
    int pickIndex() {
        int x = rand() % n;
        int head = 0, tail = sum.size() - 1;
        while(head < tail){
            int mid = (head + tail) >> 1;
            if(sum[mid] <= x) head = mid + 1;
            else tail = mid;
        }
        return head;
    }
};
  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值