关于二叉树问题

有一颗二叉树,最大深度为D,且所有的叶子的深度都相同。所有结点从上到下从左到右标号为1,2,3,4…2^D-1。在结点1处放一个小球,它会往下落。每一个内结点上都有一个开关,初始值全部关闭,当每次小球落到一个开关上时,状态会发生改变。当小球达到一个内结点时,如果结点开关关闭,则往左,否则往右,知道走到叶子结点。一些小球从结点1处依次开始下落,最后一个小球会落到哪里,输入叶子深度D和小球个数I,输出第I个小球最后所在的叶子编号,假设I不超过整棵树的叶子个数。D <= 20。输入最多包含1000组数据

样例输入
4 2
3 4
10 1
2 2
8 128
16 12345

样例输出
12
7
512
3
255
36358

#include<stdio.h>
#include<string.h>

const int MAXD = 20;

int s[1<<MAXD];//最大结点个数为2^maxd-1 

int main()
 {
      int D, I;
      while(scanf("%d%d", &D, &I) == 2)
        {
            memset(s, 0, sizeof(s));        //首先将所有开关置0 
            int k, n = (1<<D)-1;            //n是最大的结点编号 
            for(int i = 0; i < I; i++)      //连续让I个小球下落 
            {
                k = 1;
                for(;;)
                {
                    s[k] = !s[k];
                    k = s[k] ? k*2 : k*2+1; //根据开关状态选择下落方向 
                    if(k > n) break;        //已经落 "出界"了 
                }
            }
            printf("%d\n", k/2);            //"出界"之前的叶子编号 
        }
      return 0;
 }

下面代码进行优化后节省下一个巨大数组的空间

#include<stdio.h>
int main() {
  int D, I;
  while(scanf("%d%d", &D, &I) == 2) 
  {
    int k = 1;
    for(int i = 0; i < D-1; i++)
      if(I%2) { k = k*2; I = (I+1)/2; }
      else { k = k*2+1; I /= 2; }
    printf("%d\n", k);
  }
  return 0;
}
<think> 根据用户查询和提供的引用内容,用户希望了解关于二叉树程题。引用中包含了二叉树的基本操作、创建、遍历、镜像转换以及单值二叉树的判断等程题示例。 我将从以下几个方面组织回答: 1. 二叉树基本结构与创建(引用1、3) 2. 二叉树镜像(引用4) 3. 单值二叉树判断(引用5) 4. 其他常见二叉树程题类型 注意:所有代码示例将使用用户提供的引用中的语言(C/C++/Java),并保持原样。同时,我会按照系统指令要求,对数学表达式使用$...$格式,独立公式使用$$...$$格式(但二叉树问题中数学公式较少,可能不涉及),并生成相关问题。 </think>以下是关于二叉树程题的总结,结合引用内容及常见考点: ### 一、二叉树基本操作(引用1、3) 1. **节点结构与初始化**(C++示例): ```cpp template<class T> struct BinaryTreeNode { T _value; BinaryTreeNode<T>* _pleft; BinaryTreeNode<T>* _pright; BinaryTreeNode(const T& value) : _value(value), _pleft(NULL), _pright(NULL) {} }; ``` 2. **二叉树创建**(前序遍历输入,'#'表示空): ```c BTnode* treepush(char* ps, int* i) { if (ps[*i] == '#') { (*i)++; return NULL; } BTnode* root = treeinit(ps[*i]); // 创建节点 (*i)++; root->left = treepush(ps, i); // 递归构建左子树 root->right = treepush(ps, i); // 递归构建右子树 return root; } ``` ### 二、常见程题型 1. **二叉树镜像**(引用4) - **递归法**(Java示例): ```java public void Mirror(TreeNode root) { if (root == null) return; swap(root); // 交换左右子树 Mirror(root.left); Mirror(root.right); } private void swap(TreeNode root) { TreeNode temp = root.left; root.left = root.right; root.right = temp; } ``` - **非递归法**:使用栈/队列层序遍历并交换节点 2. **单值二叉树判断**(引用5) ```c bool isUnivalTree(struct TreeNode* root) { if (root == NULL) return true; if (root->left && root->left->val != root->val) return false; if (root->right && root->right->val != root->val) return false; return isUnivalTree(root->left) && isUnivalTree(root->right); } ``` 3. **其他高频题型**(引用2): - 求二叉树深度 - 判断平衡二叉树 - 二叉树路径总和 - 最近公共祖先(LCA) - 序列化/反序列化二叉树 ### 三、核心解题技巧 1. **递归思想**:90%二叉树问题可用递归解决,注意终止条件(节点为空/叶子节点) 2. **遍历框架**: ```python def traverse(root): if not root: return # 前序位置 traverse(root.left) # 中序位置 traverse(root.right) # 后序位置 ``` 3. **空间优化**:迭代法常用栈/队列代替递归栈
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值