版权声明:我的GitHub:https://github.com/617076674。真诚求星! https://blog.csdn.net/qq_41231926/article/details/84888050
我的数据结构与算法题目集代码仓:https://github.com/617076674/Data-structure-and-algorithm-topic-set
原题链接:https://pintia.cn/problem-sets/15/problems/858
题目描述:
知识点:树的中序遍历、递归
思路一:用中序遍历是否递增来判别K1是否满足二分搜索树的性质,用后序遍历,即递归判别K2是否满足最小堆的性质
有一种很容易犯的错误,是简单地用后序遍历进行判断K1是否满足二分搜索树的性质,即递归地分别检查左右子树是否满足二分搜索树的性质:若是,则比较根节点的K1与其左右孩子K1的相对大小,若根节点K1居中,则返回真;否则返回假。
这种做法无法通过测试点4,其错误的根源在于,二分搜索树的根节点K1不仅仅要大于其左孩子的K1,而是必须大于整个左子树里所有节点的K1;对右子树同理。所以如果用递归后序遍历进行判断,我们不仅需要判断子树是否满足二分搜索树的性质,还必须通过参数传递该子树中所有节点的最大和最小K1值。需要判断根节点的K1值是否居于左子树的最大值和右子树的最小值之间。
时间复杂度是O(N)。由于采用静态数组的形式在全局变量里定义了节点,因此空间复杂度是O(1000)。
C++代码:
#include<iostream>
#include<vector>
using namespace std;
struct node{
int K1, K2, lchild, rchild;
};
int N;
node Node[1000];
vector<int> inOrder;
void inOrderTraversal(int head);
bool judge1(int head);
bool judge2(int head);
int main(){
std::ios::sync_with_stdio(false);
cin >> N;
bool flag[N];
fill(flag, flag + N, false);
for(int i = 0; i < N; i++){
cin >> Node[i].K1 >> Node[i].K2 >> Node[i].lchild >> Node[i].rchild;
if(Node[i].lchild != -1){
flag[Node[i].lchild] = true;
}
if(Node[i].rchild != -1){
flag[Node[i].rchild] = true;
}
}
int head = -1;
for(int i = 0; i < N; i++){
if(!flag[i]){
head = i;
break;
}
}
if(judge1(head) && judge2(head)){
cout << "YES" << endl;
}else{
cout << "NO" << endl;
}
return 0;
}
void inOrderTraversal(int head){
if(head == -1){
return;
}
inOrderTraversal(Node[head].lchild);
inOrder.push_back(Node[head].K1);
inOrderTraversal(Node[head].rchild);
}
bool judge1(int head){
inOrderTraversal(head);
for(int i = 1; i < inOrder.size(); i++){
if(inOrder[i] <= inOrder[i - 1]){
return false;
}
}
return true;
}
bool judge2(int head){
if(head == -1){
return true;
}
if(Node[head].lchild != -1 && Node[Node[head].lchild].K2 <= Node[head].K2){
return false;
}
if(Node[head].rchild != -1 && Node[Node[head].rchild].K2 <= Node[head].K2){
return false;
}
return judge2(Node[head].lchild) && judge2(Node[head].rchild);
}
C++解题报告:
思路二:用思路一中的分析,即判断根节点的K1值是否居于左子树的最大值和右子树的最小值之间,以此递归判断K1是否满足二分搜索树的性质
我们需要两个函数:
(1)int findMin(int head):用以寻找以head为根节点的树中的最小K1值。
(2)int findMax(int head):用以寻找以head为根节点的树中的最大K1值。
时间复杂度分析比较复杂。空间复杂度是O(1000)。
C++代码:
#include<iostream>
using namespace std;
struct node {
int K1, K2, lchild, rchild;
};
int N;
node Node[1000];
int findMin(int head);
int findMax(int head);
bool judge1(int head);
bool judge2(int head);
int main() {
std::ios::sync_with_stdio(false);
cin >> N;
bool flag[N];
fill(flag, flag + N, false);
for(int i = 0; i < N; i++) {
cin >> Node[i].K1 >> Node[i].K2 >> Node[i].lchild >> Node[i].rchild;
if(Node[i].lchild != -1) {
flag[Node[i].lchild] = true;
}
if(Node[i].rchild != -1) {
flag[Node[i].rchild] = true;
}
}
int head = -1;
for(int i = 0; i < N; i++) {
if(!flag[i]) {
head = i;
break;
}
}
if(judge1(head) && judge2(head)) {
cout << "YES" << endl;
} else {
cout << "NO" << endl;
}
return 0;
}
int findMin(int head){
if(Node[head].lchild == -1 && Node[head].rchild == -1){
return Node[head].K1;
}
if(Node[head].lchild != -1 && Node[head].rchild != -1){
return min(Node[head].K1, min(findMin(Node[head].lchild), findMin(Node[head].rchild)));
}
if(Node[head].lchild != -1 && Node[head].rchild == -1){
return min(Node[head].K1, findMin(Node[head].lchild));
}
return min(Node[head].K1, findMin(Node[head].rchild));
}
int findMax(int head){
if(Node[head].lchild == -1 && Node[head].rchild == -1){
return Node[head].K1;
}
if(Node[head].lchild != -1 && Node[head].rchild != -1){
return max(Node[head].K1, max(findMax(Node[head].lchild), findMax(Node[head].rchild)));
}
if(Node[head].lchild != -1 && Node[head].rchild == -1){
return max(Node[head].K1, findMax(Node[head].lchild));
}
return max(Node[head].K1, findMax(Node[head].rchild));
}
bool judge1(int head) {
if(head == -1) {
return true;
}
if(Node[head].lchild != -1 && findMax(Node[head].lchild) >= Node[head].K1) {
return false;
}
if(Node[head].rchild != -1 && findMin(Node[head].rchild) <= Node[head].K1) {
return false;
}
return judge1(Node[head].lchild) && judge1(Node[head].rchild);
}
bool judge2(int head) {
if(head == -1) {
return true;
}
if(Node[head].lchild != -1 && Node[Node[head].lchild].K2 <= Node[head].K2) {
return false;
}
if(Node[head].rchild != -1 && Node[Node[head].rchild].K2 <= Node[head].K2) {
return false;
}
return judge2(Node[head].lchild) && judge2(Node[head].rchild);
}
C++解题报告: