红黑树的平衡条件
- 每个节点非黑即红
- 根节点是黑色
- 叶节点(NIL即虚拟空节点)是黑色
- 如果一个节点是红色,则它的两个子节点都是黑色的
- 从根节点出发到所有叶节点路径上,黑色节点数量相同
问题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;
}
};