体系班第十三节

1判断完全二叉树递归做法

有四种情况:1 左树完全,右数满,且左高为右高加一

2左满 ,右满,左高为右高加一

3左满,右完全,左右高相等

4左右均满且高相等

cpp 复制代码
#include<iostream>
#include<algorithm>
using namespace std;
class TreeNode {
public:
	int val;
	TreeNode* left;
	TreeNode* right;
	TreeNode(int a) :val(a), left(nullptr), right(nullptr) {};
};
struct info {
	int height;
	bool iscbt;
	bool isfull;
	info(int a,bool b,bool c):height(a),iscbt(b),isfull(c){}
};
info process(TreeNode* head)
{
	if (head == nullptr)
		return info(0, true, true);
	info leftinfo = process(head->left);
	info rightinfo = process(head->right);
	int height = max(leftinfo.height, rightinfo.height) + 1;
	bool isfull = leftinfo.isfull && rightinfo.isfull && leftinfo.height == rightinfo.height;
	bool iscbt = false;
	if (leftinfo.isfull && rightinfo.isfull && leftinfo.height - rightinfo.height == 1)
		iscbt = true;
	if (leftinfo.isfull && rightinfo.isfull && leftinfo.height ==rightinfo.height )
		iscbt = true;
	if (leftinfo.iscbt && rightinfo.isfull && leftinfo.height - rightinfo.height == 1)
		iscbt = true;
	if (leftinfo.isfull && rightinfo.iscbt && leftinfo.height == rightinfo.height)
		iscbt = true;
	return info(height, iscbt, isfull);
}
bool iscbt(TreeNode* head)
{
	if (head == nullptr)
		return true;
	return process(head).iscbt;
}

2 给定一棵二叉树的头节点head,返回这颗二叉树中最大的二叉搜索子树的头节点

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class TreeNode {
public:
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int data) : val(data), left(nullptr), right(nullptr) {}
};
struct info {
    TreeNode* node;//最大搜索子树头结点
    int maxsize;
    int min;
    int max;
    info(TreeNode *a,int b,int c,int d):node(a),maxsize(b),min(c),max(d){}
};
info* process(TreeNode* head)
{
    if (head == nullptr)
        return nullptr;
    info* leftinfo = process(head->left);
    info* rightinfo = process(head->right);
    int maxval = head->val;
    int minval = head->val;
    TreeNode* ans = nullptr;
    int size = 0;
    if (leftinfo != nullptr)
    {
        maxval = max(maxval, leftinfo->max);
        minval = min(minval, leftinfo->min);
        ans = leftinfo->node;
        size = leftinfo->maxsize;
    }
    if (rightinfo != nullptr)
    {
        maxval = max(maxval, rightinfo->max);
        minval = min(minval, rightinfo->min);
        if (rightinfo->maxsize > size)
        {
            ans = rightinfo->node;
            size = rightinfo->maxsize;
        }
    }
    //当能构成搜索二叉树时
    if((leftinfo==nullptr?true:(leftinfo->node==head->left&&leftinfo->max<head->val))
        && (rightinfo == nullptr ? true : (rightinfo->node == head->right && rightinfo->min > head->val)))
    {
       ans=head;
       //一定要记得判空
       size = (leftinfo == nullptr ? 0 : leftinfo->maxsize) + (rightinfo == nullptr ? 0 : leftinfo->maxsize) + 1;
    }
    return new info(ans, size, minval, maxval);
}
TreeNode* maxSubBSTHead2(TreeNode* head)
{
    if (head == nullptr)
        return nullptr;
    return process(head)->node;
}

3给定一棵二叉树的头节点head,和另外两个节点a和b,返回a和b的最低公共祖先

法1:用哈希表记下所有节点父节点,将一个节点不停地向上,这其中经过的节点放入一个集合中

再在另一个节点从上遍历,一遍查找是否在集合中已经存在过,找到的第一个即为答案

cpp 复制代码
#include <iostream>
#include <unordered_map>
#include <unordered_set>
using namespace std;
class TreeNode {
public:
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int data) : val(data), left(nullptr), right(nullptr) {}
};
void fillmap(TreeNode* head, unordered_map<TreeNode*, TreeNode*> &map)
{
    if (head->left != nullptr)
    {
        map[head->left] = head;
        fillmap(head->left, map);
    }
    if (head->right != nullptr)
    {
        map[head->right] = head;
        fillmap(head->right, map);
    }
}
TreeNode* lowestAncestor(TreeNode* head, TreeNode* p, TreeNode* q)
{
    if (head == nullptr)
        return nullptr;
    unordered_map<TreeNode*, TreeNode*> map;//记录所有节点的父节点
    map[head] = nullptr;
    fillmap(head,map);
    unordered_set<TreeNode*> set;
    TreeNode* cur = p;
    set.insert(cur);
    while (map[cur] != nullptr)
    {
        cur = map[cur];
        set.insert(cur);
    }
    cur = q;
    while (set.find(cur) == set.end())
    {
        cur = map[cur];
    }
    return cur;
}

法二:递归套路,会聚点与x有关还是无关:无关:已经在左或右树右答案,或这棵树a,b没找全

x是答案:左发现一个,右发现一个

x本身就是a,然后左右发现了b x本身就是b,左右发现a

cpp 复制代码
#include <iostream>
using namespace std;

// 节点类
class Node {
public:
    int value;
    Node* left;
    Node* right;

    Node(int data) : value(data), left(nullptr), right(nullptr) {}
};
// 最低公共祖先函数
Node* lowestAncestor2(Node* head, Node* a, Node* b) {
    return process(head, a, b).ans;
}

// 信息结构体
struct Info {
    bool findA;
    bool findB;
    Node* ans;

    Info(bool fA, bool fB, Node* an) : findA(fA), findB(fB), ans(an) {}
};

// 处理函数
Info process(Node* x, Node* a, Node* b) {
    if (x == nullptr) {
        return Info(false, false, nullptr);
    }

    Info leftInfo = process(x->left, a, b);
    Info rightInfo = process(x->right, a, b);

    bool findA = (x == a) || leftInfo.findA || rightInfo.findA;//不要忘了x本身就是a的情况
    bool findB = (x == b) || leftInfo.findB || rightInfo.findB;
    Node* ans = nullptr;

    if (leftInfo.ans != nullptr) {
        ans = leftInfo.ans;
    }
    else if (rightInfo.ans != nullptr) {
        ans = rightInfo.ans;
    }
    else {
        if (findA && findB) {
            ans = x;
        }
    }

    return Info(findA, findB, ans);
}

4 派对的最大快乐值

员工信息的定义如下:

class Employee {

public int happy; // 这名员工可以带来的快乐值

List<Employee> subordinates; // 这名员工有哪些直接下级

}

公司的每个员工都符合 Employee 类的描述。整个公司的人员结构可以看作是一棵标准的、 没有环的多叉树

树的头节点是公司唯一的老板,除老板之外的每个员工都有唯一的直接上级

叶节点是没有任何下属的基层员工(subordinates列表为空),除基层员工外每个员工都有一个或多个直接下级

这个公司现在要办party,你可以决定哪些员工来,哪些员工不来,规则:

1.如果某个员工来了,那么这个员工的所有直接下级都不能来

2.派对的整体快乐值是所有到场员工快乐值的累加

3.你的目标是让派对的整体快乐值尽量大

给定一棵多叉树的头节点boss,请返回派对的最大快乐值。

分情况:x来,x不来,定义一个结构体,保存两个值,x来时候的最大值,x不来时候的最大值

cpp 复制代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
struct employee {
	int happy;
	vector<employee*> nexts;
	employee(int h):happy(h),nexts(){}
};
struct info {
	int yes;
	int no;
	info(int a,int b):yes(a),no(b){}
};
info process(employee* head)
{
	if (head == nullptr)
		return info(0, 0);
	int yes = head->happy;
	int no = 0;
	for (employee* a : head->nexts)
	{
		info nextinfo = process(a);
		yes += nextinfo.no;
		no += max(nextinfo.yes, nextinfo.no);
	}
	return info(yes, no);
}
int maxhappy(employee* head)
{
	info allinfo = process(head);
	return max(allinfo.no, allinfo.yes);
}

5给定一个由字符串组成的数组strs,必须把所有的字符串拼接起来,返回所有可能的拼接结果中字典序最小的结果

贪心:局部最小得全体最优解,有时候可能会有错

字典序:字符串排大小,长度一样比数字大小

长度不同:较短的补上最小的阿斯克码值,然后与长的比较

证明过程:得先证明排序过程具有传递性 ,像石头剪刀布就没有传递性

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class compare {
public:
	bool operator()(string a, string b)
	{
		return (a + b) < (b + a);
	}
};
string lowestString(vector<string> str)
{
	if (str.empty())
		return "";
	sort(str.begin(), str.end(), compare());
	string a="";
	for (string c : str)
	{
		a += c;
	}
	return a;
}
相关推荐
汉字萌萌哒几秒前
【2022 CCF 非专业级别软件能力认证第一轮(CSP-J1)入门级 C++语言试题及解析】
数据结构·c++·算法
th新港2 分钟前
CCF201909_1
数据结构·c++·算法·ccf
意如流水任东西2 分钟前
[C++]类和对象(上)
开发语言·c++
清纯世纪7 分钟前
基于深度学习的图像分类或识别系统(含全套项目+PyQt5界面)
开发语言·python·深度学习
孤寂大仙v8 分钟前
【C++】STL----stack和queue常见用法
开发语言·c++
孤华暗香12 分钟前
Python快速入门 —— 第三节:类与对象
开发语言·python
一丝晨光27 分钟前
逻辑运算符
java·c++·python·kotlin·c#·c·逻辑运算符
元气代码鼠28 分钟前
C语言程序设计(进阶)
c语言·开发语言·算法
霍霍哈嗨40 分钟前
【QT基础】创建项目&项目代码解释
开发语言·qt
friklogff41 分钟前
【C#生态园】从图像到视觉:Emgu.CV、AForge.NET、OpenCvSharp 全面解析
开发语言·c#·.net