二叉树中的奇偶树问题

news2024/11/30 15:41:23

目录

一·题目:

二·思路汇总:

1.二叉树层序遍历:

1.1题目介绍:

1.2 解答代码(c版):

1.3 解答代码(c++版):

1.4 小结一下:

2.奇偶树分析:

2.1 被leetcode强制否定的思路:

2.2被迫转换的思路:

三·解答代码:


一·题目:

leetcode链接: 1609. 奇偶树 - 力扣(LeetCode)

二·思路汇总:

1.二叉树层序遍历:

1.1题目介绍:

解答这道题,其实首先可以说是和leetcode上的另一道题相关,即二叉树的层序遍历:

leetcode链接:. - 力扣(LeetCode) 

对这道题也就不过多解释了,只是用到了这道题的相关代码,可以说是奇偶树是基于这道题。

1.2 解答代码(c版):

//思路:利用队列先进先出,后进后出原则,把树的节点放入,每次取出队列第一个元素,就把它的val按照顺序放入数组
//然后保存并pop掉,放入左右孩子节点(不为NULL),由于是放入二维数组的每一行,故利用for循环,每次计算队列数据个数来控制
//最后注意每次放入二维数组每一行后既for完成一次换行。

//接口函数要完成的任务:1·返回层序遍历树得到的按规定的二维数组指针.2·改变并得到二维数组的总行数。3·改变对应的每行的列数
 typedef  struct TreeNode *qdatatype;
typedef struct Qnode {
	struct Qnode* next;
	qdatatype data;
}Qnode;
typedef struct queue {
	int size;
	Qnode* head;
	Qnode* tail;
}queue;
void Queueinit(queue* p) {
	assert(p);
	p->head = p->tail = NULL;
	p->size = 0;
}


void Queuedestroy(queue* p) {
	assert(p);
	Qnode* cur = p->head;
	while (cur) {
		Qnode* next = cur->next;
		free(cur);
		cur = next;
	}
	p->size = 0;
	p->tail = p->head = NULL;
}
void Queuebackpush(queue* p, qdatatype x) {
	assert(p);
	Qnode* newnode = (Qnode*)malloc(sizeof(Qnode));
	if (newnode == NULL) {
		perror(malloc);
		return;
	}
	newnode->next = NULL;
	newnode->data = x;
	if (p->tail == NULL) {
		p->head = p->tail = newnode;
	}
	else {
		p->tail->next = newnode;
		p->tail = newnode;
	}
	p->size++;


}
qdatatype Queuefrontdata(queue* p) {
	assert(p);
	assert(p->size > 0);
	return p->head->data;
}
bool QueueEmpty(queue* p) {
	assert(p);
	return p->size == 0;
}
void Queuefrontpop(queue* p) {
	assert(p);
	assert(p->size > 0);
	if (p->head->next == NULL) {
		free(p->head);
		p->head = p->tail = NULL;
	}
	else {
		Qnode* next = p->head->next;
		free(p->head);
		p->head = next;
	}
	p->size--;
}
int Queuesize(queue* p) {
	assert(p);
	return p->size;
}
//以上是开辟的队列

int** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes) {
    * returnSize=0;
    int**pp=(int**)calloc(2000,sizeof(int*));//利用二级指针来开辟二维数组,首先开辟2000行,可以理解为下面再利用每一行的首地址来开辟每一行的一维数组,即列数
    if(root==NULL){
 return NULL;
    }//空树直接返回NULL
     queue q;
	Queueinit(&q);
	Queuebackpush(&q, root);//先放入树的根节点
    int row=0;//树的层数
    int count=0;//每层树的节点的个数
    *returnColumnSizes = (int*)malloc(sizeof(int) * 2000);//在外部传的是&arr通过函数来改变数组内的数据,故用二级指针接受
    //为每行开辟2000个空间
	while (!QueueEmpty(&q)) {
       count= Queuesize(&q);//当pop掉上一行所有节点,重新计算队列数据个数即下面要放入数组的每行的数据个数
       (*returnColumnSizes)[row]=count;//记录每行列数
       pp[row]=(int*)calloc(count,sizeof(int));//放入数组:得到每行的首地址,在此开辟一维数组,即二维数组每行的列数
       for(int i=0;i<count;i++){
        struct TreeNode*ret=Queuefrontdata(&q);
        pp[row][i]=ret->val;
        Queuefrontpop(&q);
        if (ret->left!= NULL) {
			
			Queuebackpush(&q, ret->left);
		}
		if (ret->right!= NULL) {
			
			Queuebackpush(&q, ret->right);
		}
       }
		//利用for循环将上一层节点所连的左右子节点放入,满足队列内数据个数就是下一层的行的列数
		row++;
	}
	Queuedestroy(&q);
    
    *returnSize=row;

    return pp;


}

1.3 解答代码(c++版):
 

//思路:把树的节点入队列,每次队列数据入v后pop调,之后拉进它的左右孩子入队,队列的大小就是二维数组每行的数据数,依次两个循环嵌套。
class Solution{
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<int>v;
         vector<vector <int>>vv;
         
       queue<TreeNode*> q;
        if(root==NULL){
            return vv;
        }
       q.push(root);
       while(!q.empty()){
       int size=q.size();
       int count=size;//记录每行大小也是push——back次数
       v.clear();//刷新v里面的数据
       while(count--){
       //vv[row].push_back(q.front()->val);因为一开始定义的vv没有开辟空间,故不能这样用下标访问,只有下面的push_back才
       //开了空间,故可以直接插入数据。类似于用malloc给指针开辟空间,再用下标访问,而这里相当于用malloc故访问越界
       v.push_back(q.front()->val);
        TreeNode*tmp=q.front();//保存节点指针方便后面push
        q.pop();
        if(tmp->left!=NULL){
            q.push(tmp->left);
        }
         if(tmp->right!=NULL){
            q.push(tmp->right);
        }
       }

      vv.push_back(v);//每push完一层就加到vector后面。
    }
    return vv;
    }
};

1.4 小结一下:

根据对于同一道题的解答代码长度和复杂度上,明显c++直接占极大优势,感觉当初花很长时间的c代码直接让c++代码瞬间秒杀,而且难度也减小,不亏是c的升级版,感觉爱不释手了。

2.奇偶树分析:

2.1 被leetcode强制否定的思路:

先说一下一开始吧,本以为,如果先把它按照层序遍历到二维数组的话,后面再对已知条件进行一次判断的话,本来以为可以通过(当看到测试用例过了):

然而当提交的时候,果然还是被leetcode给算计住了(其实当看到val精确到10^6就觉得可能会来这一套,说实话也没太出乎意料吧):

 

这里用了简单hash表以及is_sorted() 等最后来判断是否符合,不过这下子只能换思路咯!

错误代码(仅参考一下这个思路吧,不过也pass掉咯):

class Solution {
public:
    bool isEvenOddTree(TreeNode* root) {
          vector<int>v;
          vector<vector <int>>vv;
           queue<TreeNode*> q;
         if (root == NULL) {
          return false;
          }
         q.push(root);
         
        while (!q.empty()) {
        int size = q.size();
        int count = size;//记录每行大小也是push——back次数
        v.clear();//刷新v里面的数据
        while (count--) {
         //vv[row].push_back(q.front()->val);因为一开始定义的vv没有开辟空间,故不能这样用下标访问,只有下面的push_back才

         //开了空间,故可以直接插入数据。类似于用malloc给指针开辟空间,再用下标访问,而这里相当于用malloc故访问越界   
          
                    v.push_back(q.front()->val);
         TreeNode* tmp = q.front();//保存节点指针方便后面push
         q.pop();
         if (tmp->left != NULL) {
             q.push(tmp->left);
         }
         if (tmp->right != NULL) {
             q.push(tmp->right);
         }
     }

     vv.push_back(v);//每push完一层就加到vector后面。

 }

  if(vv[0][0]%2==0){
        return false;
    }
    
  for(int i=0;i<vv.size();i++){

       int hash[1000001]={0};
       for(int j=0;j<vv[i].size();j++){

         if(i%2==0&&vv[i][j]%2==0){
            return false;
        }
        if(i%2!=0&&vv[i][j]%2!=0){
            return false;
        }

        if(hash[vv[i][j]]>=1){
            return false;
        }
       
        hash[vv[i][j]]++;
       }
         
        if(i%2==0){
           if(is_sorted(vv[i].begin(),vv[i].end(),less<int>())){
            
           }
           else{
        
            return false;
           }
        }
        else{
    if(is_sorted(vv[i].begin(),vv[i].end(),greater<int>())){
            
           }
           else{
            return false;
           }
        }
      
  }
  return true;
    }
};

 

2.2被迫转换的思路:

下面于是就想着可以在放入内部嵌套的vector 的过程中来判断是否符合。

由于把它依靠队列放入vector模拟的二维数组再判断奇偶层对应的奇偶数已经严格递增的话可能超过了时间限制,故可以换个思路,考虑当由队列放入v中就按照顺序筛选,(由于只要出现一种不符合条件的情况,它就不是奇偶数,故找到不合题意就直接给它false,剩下的直接最后true就OK)

筛选条件:level要么是奇数要么是偶数,为奇的话,插入的数据应该是偶,为偶的话,插入的数据应该是奇,否则直接false。 偶奇:如果是第一个先直接插入,但是也要有个比较v中的数据要小于要插入的才插入,否则也直接false。

 同理 奇偶也是如此:如果是第一个先直接插入,但是也要有个比较v中的数据要大要插入的才插入,否则也直接false。

   

    步骤总结:

   1.先模拟二叉树进入vector模拟的二维数组过程

    2.进入vector的时候加上筛选条件

最后也是成功被leetcode放行通过了:

尽管这种方法效率有点低吧!!!

三·解答代码:

class Solution {
public:
    bool isEvenOddTree(TreeNode* root) {
        vector<int>v;
        vector<vector <int>>vv;
        queue<TreeNode*> q;
        if (root == NULL) {
            return false;
        }
        q.push(root);
        int row = -1;
        while (!q.empty()) {
            int size = q.size();
            row++;//记录level的值
            int count = size;//记录每行大小也是push——back次数
            v.clear();//刷新v里面的数据
            while (count--) {
                //vv[row].push_back(q.front()->val);因为一开始定义的vv没有开辟空间,故不能这样用下标访问,只有下面的push_back才

                //开了空间,故可以直接插入数据。类似于用malloc给指针开辟空间,再用下标访问,而这里相当于用malloc故访问越界   
                if (row % 2 == 0 && q.front()->val % 2 != 0) {//判断为偶奇

                    if (v.size() == 0) {
                        v.push_back(q.front()->val);
                    }
 else if (v.end() == find(v.begin(), v.end(), q.front()->val) && v[v.size() - 1] < q.front()->val)
  {
                        v.push_back(q.front()->val);//判断严格升序
                    }
                    else {
                        return false;//非严格升序
                    }
                }


                else if (row % 2 != 0 && q.front()->val % 2 == 0) {//判断为奇偶
                    if (v.size() == 0) {
                        v.push_back(q.front()->val);
                    }
else  if (v.end() == find(v.begin(), v.end(), q.front()->val) && v[v.size() - 1]> q.front()->val)
                    {
                        v.push_back(q.front()->val);//判断严格降序
                    }
                    else {
                        return false;//非严格降序
                    }

                }


                else {//非->直接返false
                    return false;
                }

                TreeNode* tmp = q.front();//保存节点指针方便后面push
                q.pop();
                if (tmp->left != nullptr) {
                    q.push(tmp->left);
                }
                if (tmp->right != nullptr) {
                    q.push(tmp->right);
                }
            }

            vv.push_back(v);//每push完一层就加到vector后面。

        }
        return true;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2059576.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【学习笔记】Matlab和python双语言的学习(一元线性回归模型)

文章目录 前言一、一元线性回归回归分析的一般步骤一元线性回归的基本形式回归方程参数的最小二乘法估计对回归方程的各种检验估计标准误差的计算回归直线的拟合优度判定系数显著性检验 二、示例三、代码实现----Matlab1.Matlab 的 regress 函数2.Matlab 代码 四、代码实现----…

我像只鱼儿在你的进程池~

我像只鱼儿在你的进程池&#xff5e; 只为你守候这进程间通信&#xff5e; 一点都不押韵 点踩吧 父进程是master&#xff0c;它提前创建出一堆紫禁城&#xff0c;如果有命令就交给子进程去执行&#xff08;和shell不一样&#xff0c;shell是有任务才去创建子进程&#xff09…

吹爆SyntaxFlow!数据流分析实战解析

正文开始前辟个谣先 最近有小伙伴来问闭源收费的事 牛牛郑重告知大家 目前还没有这个计划 请大家放心使用 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 样例解析在之前的SyntaxFlow教程中&#xff0c;我们已经看到了非常多的代码样例进行数据流分…

广东失业领取指南 记录自己的失业

1. 前言 坐标广州&#xff0c;七月底就被裁员领取n1解放了&#xff0c;趁着这次机会&#xff0c;也想着躺几个月后再去上班&#xff0c;现在工作也不好找&#xff0c;加上之前加班实在是消耗太大了。想着躺也不能干躺&#xff0c;去申请一下失业金每个月还有补贴用&#xff0c…

[数据集][目标检测]锤子检测数据集VOC+YOLO格式1510张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1510 标注数量(xml文件个数)&#xff1a;1510 标注数量(txt文件个数)&#xff1a;1510 标注…

悟空降世 撼动全球

文&#xff5c;琥珀食酒社 作者 | 积溪 一只猴子能值多少钱&#xff1f; 答案是&#xff1a;13个小目标 这两天 只要你家没有断网 一定会被这只猴子刷屏 它就是咱国产的3A游戏 《黑神话&#xff1a;悟空》 这只猴子到底有多火&#xff1f; 这么跟你说吧 茅台见了它都…

TPM管理培训值不值得去?

TPM管理培训是否值得去&#xff0c;取决于多个因素&#xff0c;包括个人职业发展需求、所在企业的情况以及培训内容和质量等&#xff0c;具体如深圳TPM管理咨询公司下文所述&#xff1a; 一、个人职业发展需求 - 从事设备管理相关工作&#xff1a;如果您的工作涉及设备维护、生…

数聚股份携手销售易闪耀CDIE数字化创新博览会,开启企业数字化转型加速器

6月25日-26日&#xff0c;第十届CDIE数字化创新博览会在上海张江科学会堂隆重举办&#xff0c;本次博览会大咖云集&#xff0c;汇聚零售、快消、制造、医疗、金融、出海等领域的企业高管和部门负责人&#xff0c;打破行业边界、共话数字化痛点和热点话题。 时隔一年&#xff…

UDS 诊断 - ReadMemoryByAddress(按地址读取内存)(0x23)服务

UDS 诊断服务系列文章目录 诊断和通信管理功能单元 UDS 诊断 - DiagnosticSessionControl&#xff08;诊断会话控制&#xff09;&#xff08;0x10&#xff09;服务 UDS 诊断 - ECUReset&#xff08;ECU重置&#xff09;&#xff08;0x11&#xff09;服务 UDS 诊断 - SecurityA…

黑神话孙悟空,自媒体小白如何蹭这波流量!

当下&#xff0c;黑神话孙悟空的热度如熊熊烈火&#xff0c;席卷了整个游戏世界。 只要与这个话题沾边&#xff0c;似乎就能轻松吸引大量关注。 那么&#xff0c;对于不怎么懂自媒体运营的小伙伴来说&#xff0c;该如何抓住这个机遇呢&#xff1f; 别担心&#xff0c;我们可以…

LearnOpenGL——延迟渲染学习笔记

延迟渲染学习笔记 一、基本概念二、G-BufferMRT 三、Lighting Pass四、结合延迟渲染和前向渲染五、更多光源 我们之前使用的一直是 前向渲染&#xff08;正向渲染 Forward Rendering&#xff09;&#xff0c;指的是在场景中根据所有光源照亮一个物体&#xff0c;之后再渲染下一…

MBR30100CT-ASEMI低压降肖特基MBR30100CT

编辑&#xff1a;ll MBR30100CT-ASEMI低压降肖特基MBR30100CT 型号&#xff1a;MBR30100CT 品牌&#xff1a;ASEMI 封装&#xff1a;TO-220 批号&#xff1a;最新 恢复时间&#xff1a;35ns 最大平均正向电流&#xff08;IF&#xff09;&#xff1a;30A 最大循环峰值反…

Django | 从中间件的角度来认识Django发送邮件功能

文章目录 概要中间件中间件 ---> 钩子实现中间件demo 邮件发送过程Django如何做邮件服务配置流程 中间件结合邮件服务实现告警 概要 摘要 业务告警 邮件验证 密码找回 邮件告警 中间件 中间件 —> ‘钩子’ 例如 访问路由 的次数【请求】 中间件类须实现下列五个方法…

商业模式画布全面解读:产品经理的实用手册

在产品经理的日常工作中&#xff0c;最基本的一项任务就是进行竞品分析和商业模式分析。一方面&#xff0c;通过竞品分析环节&#xff0c;了解当前产品的竞争力和不可替代性&#xff1b;另一方面&#xff0c;定期评估产品的商业模式是否存在风险&#xff0c;是否具有可持续性。…

Destiny of Gods首轮测试正式开启,参与玩家数量突破10万

天神风云&#xff0c;波澜再兴&#xff0c;GameFi链游聚合平台Destiny of Gods首款同名数字卡牌回合制游戏首轮测试定档8月20日20:00&#xff08;GMT8&#xff09;&#xff0c;现已正式开启&#xff01; 这是一个由人、游灵和神灵共存的世界&#xff0c;历经蛮荒时期的纷争与信…

Docker的安装与镜像配置

小编目前大一&#xff0c;刚开始着手学习SSM&#xff0c;小编会把每个框架都整理成知识点发布出来。如果你也同时在学习SSM的话&#xff0c;不妨看看我做的这个笔记。我认为同为初学者&#xff0c;我把我对知识点的理解以这种代码加观点的方式分享出来不仅加深了我的理解&#…

游泳耳机哪个牌子好?角逐必选榜的4大王者游泳耳机测评解析!

在选择游泳耳机时&#xff0c;许多消费者往往会被市场上五花八门的产品所困扰。特别是那些标榜能够防水防潮的产品&#xff0c;但实际上它们往往缺乏核心技术支持&#xff0c;存在很高的损伤风险。据调查&#xff0c;超过90%的用户反映&#xff0c;市面上的游泳耳机常常无法达到…

centos7.9离线安装kubernetes(k8s)1.28版本

文章目录 一、环境准备二、所有节点执行1、解压安装包2、创建/etc/modules-load.d/containerd.conf配置文件3、执行以下命令使配置生效4、创建/etc/sysctl.d/99-kubernetes-cri.conf配置文件5、加载ipvs内核模块–4.19以上版本内核6、授权生效7、关闭swap&#xff0c;并永久关闭…

WPF——动态排名图表实现

开发环境 VS2022 .NET 8.0 MVVM Toolkit 8.2.2 需求 开发中需要实现按照成绩动态指名&#xff0c;以展示当前的竞赛成绩的一个实时情况及变化。 即如下效果&#xff1a; 需求分析 按照接收到的信息&#xff0c;就是要将获取到的集合排序&#xff0c;并且要将排序前后的变…

什么是UDP?

UDP是工作在OSI&#xff08;开放系统互连&#xff0c;Open Systems Interconnection&#xff09;模型中传输层的协议。它使用IP作为底层协议&#xff0c;是为应用程序提供一种以最少的协议机制向其他程序发送消息的协议。其主要特点是无连接&#xff0c;不保证可靠传输和面向报…