不是吧,就因为他和面试官多聊了半个小时红黑树,进了腾讯

private K key;

private V value;

public RBNode() {

}

public RBNode(RBNode parent, RBNode left, RBNode right, boolean color, K key, V value) {

this.parent = parent;

this.left = left;

this.right = right;

this.color = color;

this.key = key;

this.value = value;

}

public RBNode getParent() {

return parent;

}

public void setParent(RBNode parent) {

this.parent = parent;

}

public RBNode getLeft() {

return left;

}

public void setLeft(RBNode left) {

this.left = left;

}

public RBNode getRight() {

return right;

}

public void setRight(RBNode right) {

this.right = right;

}

public boolean isColor() {

return color;

}

public void setColor(boolean color) {

this.color = color;

}

public K getKey() {

return key;

}

public void setKey(K key) {

this.key = key;

}

public V getValue() {

return value;

}

public void setValue(V value) {

this.value = value;

}

}

}

复制代码

左旋代码实现

/**

  • 围绕p左旋

  • p               pr(r)
    
  • / | / \

  • pl pr® => p rr

  •  / \         / \
    
  • rl  rr     pl  rl
    
  • 左旋的时候

  • p-pl 和 pr-rr的关系不变

  • pr-rl 要变为 p-rl

  •  也就是 rl要变为 p的右子节点
    
  •  同时 p要成为 rl 的父节点
    
  • 还有就是要判断 p 是否有父节点

  • 如果没有

  • r 变为 root 节点
    
  • 如果有

  • r.parent = p.parent
    
  • 还要设置 r为 p.parent 的子节点(可能左也可能右)
    
  • 如果 p.parent.left == p
    
  •    p.parent.left = r;
    
  • 否则
    
  •    p.parent.right = r;
    
  • 最后

  •   p.parent = r;
    
  •   r.left = p;
    
  • @param p

*/

private void leftRotate(RBNode p){

if(p != null){

RBNode r = p.right;

// 1.设置 pr-rl 要变为 p-rl

// 把rl设置到p的右子节点

p.right = r.left;

if(r.left != null){

// 设置rl的父节点为p

r.left.parent = p;

}

// 2.判断p的父节点情况

r.parent = p.parent; // 不管 p是否有父节点,都把这个父节点设置为 r的父节点

if(p.parent == null){

root = r; // p没有父节点 则r为root节点

}else if(p.parent.left == p){

p.parent.left = r; // 如果p为 p.parent的左子节点 则 r 也为 p.parent的左子节点

}else{

p.parent.right = r; // 反之设置 r 为 p.parent的右子节点

}

// 最后 设置 p 为 r 的左子节点

r.left = p;

p.parent = r;

}

}

复制代码

右旋实现:

/**

  • 围绕p右旋

  • @param p

*/

public void rightRotate(RBNode p){

if(p != null){

RBNode r = p.left;

p.left = r.right;

if(r.right != null){

r.right.parent = p;

}

r.parent = p.parent;

if(p.parent == null){

root = r;

}else if(p.parent.left == p){

p.parent.left = r;

}else{

p.parent.right = r;

}

r.right = p;

p.parent = r;

}

}

复制代码

2 新增节点


2-3-4树中结点添加需要遵守以下规则:

  • 插入都是向最下面一层插入

  • 升元:将插入结点由 2-结点升级成 3-结点,或由 3-结点升级成 4-结点;

  • 向 4-结点插入元素后,需要将中间元素提到父结点升元,原结点变成两个 2-结点,再把元素插入2-结点中,如果父结点也是 4-结点,则递归向上层升元,至到根结点后将树高加1;

而将这些规则对应到红黑树里,就是:

  • 新插入的结点颜色为 红色 ,这样才可能不会对红黑树的高度产生影响。

  • 2-结点对应红黑树中的单个黑色结点,插入时直接成功(对应 2-结点升元)。

  • 3-结点对应红黑树中的 黑+红 子树,插入后将其修复成 红+黑+红 子树(对应 3-结点升元);

  • 4-结点对应红黑树中的 红+黑+红 子树,插入后将其修复成 红色祖父+黑色父叔+红色孩子 子树,然后再把祖父结点当成新插入的红色结点递归向上层修复,直至修复成功或遇到 root 结点;

公式:红黑树+新增一个节点(红色)**=**对等的2-3-4树+新增一个节点

2.1 新增节点示例

我们通过新增2-3-4树的过程来映射对应的红黑树的节点新增

å¨è¿éæå¥å¾çæè¿°

2-3-4树的新增(全部在叶子节点完成)

1.新增一个节点,2 节点

å¨è¿éæå¥å¾çæè¿°

2.新增一个节点,与2节点合并,直接合并

å¨è¿éæå¥å¾çæè¿°

3.新增一个节点,与3节点合并,直接合并

å¨è¿éæå¥å¾çæè¿°

插入的值的位置会有3种情况

对应的红黑树为:

å¨è¿éæå¥å¾çæè¿°

4.新增一个节点,与4节点合并,此时需要分裂、

å¨è¿éæå¥å¾çæè¿°

插入值的位置可能是

å¨è¿éæå¥å¾çæè¿°

对应的红黑树的结构为

å¨è¿éæå¥å¾çæè¿°

2.2 新增代码实现

红黑树的新增规则我们理清楚了,接下来就可以通过Java代码来具体的实现了。

先实现插入节点,这就是一个普通的二叉树的插入

/**

  • 新增节点

  • @param key

  • @param value

*/

public void put(K key , V value){

RBNode t = this.root;

if(t == null){

// 说明之前没有元素,现在插入的元素是第一个

root = new RBNode<>(key , value == null ? key : value,null);

return ;

}

int cmp ;

// 寻找插入位置

// 定义一个双亲指针

RBNode parent;

if(key == null){

throw new NullPointerException();

}

// 沿着跟节点找插入位置

do{

parent = t;

cmp = key.compareTo((K)t.key);

if(cmp < 0){

// 左侧找

t = t.left;

}else if(cmp > 0){

// 右侧找

t = t.right;

}else{

// 插入节点的值==比较的节点。值替换

t.setValue(value==null?key:value);

return;

}
先自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以扫码领取!

img

总结

蚂蚁面试比较重视基础,所以Java那些基本功一定要扎实。蚂蚁的工作环境还是挺赞的,因为我面的是稳定性保障部门,还有许多单独的小组,什么三年1班,很有青春的感觉。面试官基本水平都比较高,基本都P7以上,除了基础还问了不少架构设计方面的问题,收获还是挺大的。


经历这次面试我还通过一些渠道发现了需要大厂真实面试主要有:蚂蚁金服、拼多多、阿里云、百度、唯品会、携程、丰巢科技、乐信、软通动力、OPPO、银盛支付、中国平安等初,中级,高级Java面试题集合,附带超详细答案,希望能帮助到大家。

蚂蚁金服5面,总结了49个面试题,遇到的面试官都是P7级别以上

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以扫码领取!

img

总结

蚂蚁面试比较重视基础,所以Java那些基本功一定要扎实。蚂蚁的工作环境还是挺赞的,因为我面的是稳定性保障部门,还有许多单独的小组,什么三年1班,很有青春的感觉。面试官基本水平都比较高,基本都P7以上,除了基础还问了不少架构设计方面的问题,收获还是挺大的。


经历这次面试我还通过一些渠道发现了需要大厂真实面试主要有:蚂蚁金服、拼多多、阿里云、百度、唯品会、携程、丰巢科技、乐信、软通动力、OPPO、银盛支付、中国平安等初,中级,高级Java面试题集合,附带超详细答案,希望能帮助到大家。

[外链图片转存中…(img-rJPJIh1J-1711484886951)]

需要更多Java资料的小伙伴可以帮忙点赞+关注,点击传送门,即可免费领取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值