拆解蓝桥杯红黑树:无限深度树的奇偶性规律与 Python 实战解法

备赛蓝桥杯:红黑树问题的核心规律(行号 n 没用?Python 实战验证)

题目重述

小蓝构造了一棵无限深度的特殊红黑树,规则如下:

节点颜色 左子节点 右子节点
红色 ® 红色 ® 黑色 (B)
黑色 (B) 黑色 (B) 红色 ®
  • 根节点 :第1行第1个,固定为 RED
  • 第n行 :共有 2n −1 个节点(1 ≤ k ≤ 2n−1)
  • 编号规则 :每行从左到右编号为 1, 2, ..., 2n−1

树的前4层可视化(括号内为 (行, 位置)):

复制代码
                R(1,1)
              /        \
         R(2,1)        B(2,2)
        /      \      /      \
    R(3,1)  B(3,2) B(3,3)  R(3,4)
    / \     / \    / \     / \
 R B   B R  B R   R B   ... (第4行)

输入格式

第一行:整数 m (查询次数,1≤m ≤105)

接下来 m 行:每行两个整数 n ,k (1≤n ≤30, 1≤k ≤2n−1)

输出格式

对每个查询,输出 REDBLACK


深度规律挖掘(附路径推导)

核心发现:颜色 = Thue-Morse 序列

k-1 转为二进制 ,统计其中 1 的个数的奇偶性

  • 偶数个 1 → RED
  • 奇数个 1 → BLACK
验证示例
查询 (n,k) k-1 二进制 1的个数 奇偶 颜色
(1,1) 0 0 0 RED
(2,2) 1 1 1 BLACK
(3,3) 2 10 1 BLACK
(3,4) 3 11 2 RED
(4,6) 5 101 2 RED
严谨数学证明(归纳法)

f (k ) 表示第 n 行第 k 个节点的颜色(0=RED, 1=BLACK)
命题f (k )=popcount(k−1)mod2

  • 基例k =1(根),k −1=0,popcount=0,f(1)=0(RED)✓
  • 归纳步 :假设第 n 行成立,考察第 n +1 行:
    • 左子节点:k ′=2k −1 → k ′−1=2(k−1) → 二进制末尾补0 → popcount 不变 → 颜色与父节点相同 ✓
    • 右子节点:k ′=2kk ′−1=2(k −1)+1 → 二进制末尾补1 → popcount+1 → 颜色翻转 ✓
      (符合"红→右=黑"、"黑→右=红"的规则)

结论 :颜色仅取决于 k −1 的二进制中 1 的个数奇偶性,与行号 *n* 无关 (但输入需保留 n 用于验证 k 合法性)


四种解法实现(含递归理解版)

方法1:递归模拟(教学理解,不推荐实战)
python 复制代码
def get_color_recursive(n, k):
    """递归模拟路径(深度=n,仅用于理解规律)"""
    if n == 1:  # 根节点
        return "RED"
    parent_k = (k + 1) // 2  # 父节点位置
    is_left = (k % 2 == 1)   # 当前是父节点的左子?
    parent_color = get_color_recursive(n-1, parent_k)
    
    if parent_color == "RED":
        return "RED" if is_left else "BLACK"
    else:
        return "BLACK" if is_left else "RED"
  • 时间O (n ) per query | 空间O (n)(递归栈)
  • 适用n ≤30 时可运行,但 m 大时超时风险高
方法2:内置函数法(推荐)
python 复制代码
def get_color_builtin(n, k):
    """利用Python内置函数:简洁高效"""
    # bin(k-1) 返回 '0b101',count('1') 统计1的个数
    return "RED" if bin(k - 1).count('1') % 2 == 0 else "BLACK"
  • 时间O (logk)(实际极快,C层实现)
  • 优势:代码最简、可读性高、AC首选
方法3:Brian Kernighan 位运算(极致优化)
python 复制代码
def get_color_bitwise(n, k):
    """清除最低位1:循环次数=1的个数"""
    x = k - 1
    parity = 0
    while x:
        parity ^= 1      # 每遇一个1翻转奇偶标志
        x &= x - 1       # Brian Kernighan: 清除最低位1
    return "RED" if parity == 0 else "BLACK"
  • 时间O (popcount(k−1)),平均优于方法2
  • 场景 :对性能极致要求(如 m=106)
方法4:查表法(超大查询量优化)
python 复制代码
# 预处理0~65535的奇偶性(16位)
PARITY_TABLE = [bin(i).count('1') % 2 for i in range(65536)]

def get_color_lookup(n, k):
    x = k - 1
    # 分高低16位查表异或
    p = PARITY_TABLE[x & 0xFFFF] ^ PARITY_TABLE[(x >> 16) & 0xFFFF]
    return "RED" if p == 0 else "BLACK"
  • 时间O(1) per query(常数极小)
  • 适用m>105 且需极致速度

多维度解法对比

方法 时间复杂度 空间 代码长度 适用场景 推荐指数
递归模拟 O (n) O (n) 15行 教学理解
内置函数 O (logk) O(1) 1行 通用首选 ⭐⭐⭐⭐⭐
位运算优化 O(pop) O(1) 5行 高性能需求 ⭐⭐⭐⭐
查表法 O(1) O(1) 8行 超大查询量 (m>105) ⭐⭐⭐

蓝桥杯实战建议 :直接使用 方法2(内置函数),简洁可靠,Python选手首选!


全面测试用例(含边界与陷阱)

基础验证
复制代码
输入:
5
1 1
2 1
2 2
3 3
4 6

输出:
RED
RED
BLACK
BLACK
RED
边界测试
用例 说明 预期
30 1 最小k(首节点) RED(k-1=0)
30 536870912 k=229(末节点) BLACK(229−1 有29个1)
15 16384 k=214 BLACK(214−1 有14个1→偶?错!214−1 二进制14个1→偶→RED?验证:214=16384, k−1=16383=111...111(14个1) → 14偶 → RED)
5 10 随机中间值 RED(9=1001₂ → 2个1)
常见错误输入(需防御性编程)
python 复制代码
# 错误1:忘记k-1(直接用k)
bin(1).count('1') % 2 = 1 → 误判(1,1)为BLACK ❌

# 错误2:混淆行列
# 误以为需用n计算,实际n仅用于验证k范围(题目保证合法可省略)

# 错误3:输入处理遗漏
# 未处理多余空格/换行 → 使用sys.stdin.read().split()最稳妥

拓展知识(提升算法视野)

与经典序列的关联
  • Thue-Morse 序列
    t**i =popcount(i )mod2,本题即 t**k −1
    → 应用于避免重复模式、分形几何、博弈论
  • 格雷码 (Gray Code)
    相邻数仅1位变化,本题路径编码本质是标准二进制
  • 汉明重量 (Hamming Weight)
    即二进制中1的个数,本题核心计算目标
思维升华
  1. 树结构 → 路径编码:将树遍历转化为二进制路径
  2. 状态转移 → 奇偶性:颜色翻转等价于模2加法
  3. 数学抽象能力:从具体规则提炼出通用数学模型
  4. 位运算实战价值:Brian Kernighan 算法在嵌入式/高性能场景广泛应用
推荐延伸阅读
  • Thue-Morse Sequence (Wikipedia)
  • 《具体数学》第1章:递归与和式(奇偶性分析)
  • LeetCode 191. Number of 1 Bits(位运算经典题)

总结与备赛建议

关键点 说明
核心规律 颜色 = (k-1).bit_count() % 2(Python 3.8+ 可直接用 .bit_count()
行号n作用 题目输入需保留,但计算中完全不需要(规律与深度无关)
最优写法 print("RED" if (k-1).bit_count() % 2 == 0 else "BLACK")
避坑指南 ① 必须 k-1 ② 注意1-based索引 ③ 无需验证k范围(题目保证合法)
蓝桥技巧 Python 3.10+ 支持 (k-1).bit_count(),比 bin().count() 更快!

最后叮嘱

遇到树结构题,先画小规模示例 → 寻找编号/路径规律 → 尝试数学归纳 → 转化为位运算/数论问题。
规律发现能力 > 代码实现能力,这才是算法竞赛的精髓!

相关推荐
肆意飞扬2 小时前
Python篇:使用conda、pip的一些命令记录
python·conda·pip
iAkuya2 小时前
(leetcode)力扣100 59括号生成(回溯||按括号序列的长度递归)
算法·leetcode·职场和发展
星月总相伴2 小时前
pycharm导包过程中,因为模块不在同一个包中可能会报错的解决问题
python
2401_841495642 小时前
【操作系统】存储器管理算法
python·操作系统·存储器管理·连续内存分配算法·非连续内存分配算法·虚拟存储页面置换算法·内存碎片整理与回收算法
渐暖°2 小时前
【leetcode算法从入门到精通】9. 回文数
算法·leetcode·职场和发展
ZPC82102 小时前
机器人手眼标定
人工智能·python·数码相机·算法·机器人
机器学习之心HML2 小时前
PGA+MKAN+Timexer时间序列预测模型Pytorch架构
人工智能·pytorch·python
查无此人byebye2 小时前
阿里开源Wan2.2模型全面解析:MoE架构加持,电影级视频生成触手可及
人工智能·pytorch·python·深度学习·架构·开源·音视频
张书名2 小时前
基于Windows11平台的北理工校园网开机自动连接脚本
python·校园网