题干如下:
红黑树是一类特殊的二叉搜索树,其中每个结点被染成红色或黑色。若将二叉搜索树结点中的空指针看作是指向一个空结点,则称这类空结点为二叉搜索树的前端结点。并规定所有前端结点的高度为-1。
一棵红黑树是满足下面“红黑性质”的染色二叉搜索树:
(1) 每个结点被染成红色或黑色;
(2) 每个前端结点为黑色结点;
(3) 任一红结点的子结点均为黑结点;
(4) 在从任一结点到其子孙前端结点的所有路径上具有相同的黑结点数。
从红黑树中任一结点x出发(不包括结点x),到达一个前端结点的任意一条路径上的黑结点个数称为结点x的黑高度,记作bh(x)。红黑树的黑高度定义为其根结点的黑高度。
给定正整数N,试设计一个算法,计算出在所有含有N个结点的红黑树中,红色内结点个数的最小值和最大值。
输入描述:
输入共一个数N。
输出描述:
输出共两行。 第一行为红色内结点个数的最小值,第二行为最大值。
示例1
输入
8
输出
1 4
题解部分:
先贴代码,使用py:
n=int(input())
k=n+1
str_k=bin(k)
_min=0
for _ in str_k:
if _ == '1':
_min+=1
_min-=1
_max=0
while k>1:
if k==2:
_max+=1
break
elif k%4==0:
_max+=k/2
k/=4
elif k%4==1:
_max+=(k-2-3)/2+1
k=(k-2-3)/4+1+1
elif k%4==2:
_max+=(k-2)/2
k=(k-2)/4+1
elif k%4==3:
_max+=(k-3)/2+1
k=(k-3)/4+1
print(_min)
print(int(_max))
(1)首先,不难发现无论是最多的情况还是最少的情况,都应当是完全二叉树。
(2)在前提(1)的情况下,红黑树上n个结点,就对应着有n+1个前端结点,这n+1个前端结点必定都是黑点。我们从n+1个前端结点开始向上演化。
(3)无论有多少个黑点,红黑树高度变化1后(保持高度一致),演化到的结果,都可以视为以下三种情况的组合:
(图像来源见水印,感谢!)
也就是说,两、三、四个黑结点如果要高度减一向上演化一层,其结果必定为这三种。
超过4个黑结点的情况可以看做几种case的组合。例如,5个前端结点就可以拆分为2+3的组合形式,再考虑2个黑点的情况。
特别的,如果只剩下两个黑点,我们就不需要再考虑高度减一的条件(无需和其他的黑点保持高度一致),可以自行决定这两个黑点的父结点的颜色。
由此可见,拆分的情况不是唯一的,而最多和最少的区别恰恰就在于拆分的方法!
不难发现:
case3,4个黑点产生了2个红点,产率1/2;
case2,3个黑点产生了1个红点,产率1/3;
case1,2个黑点产生了0个红点,产率0;
很显然,相同的黑点数目,求最小值,我们就要尽量使用case1,而求最大值就尽量使用case3!
看到这里,相信你就可以理解我的代码了。
求最小值就是尽量使用case1,演化一次,黑点数目折半。也就是不停地除以2,遇到奇数则拆解成2*n+3的形式。实际上就等同于(n+1的二进制表示中1出现的个数-1),你也可以用更加直观的方式去写。
求最大值则是尽量使用case3,也是不停的向上演化。当然,演化到只剩2个结点的时候,我们为了最大化,把根结点变成红色。
以上。转载请表明出处。