非递归解法

1. 前置知识:完全二叉树的属性

1.1 从1开始存储,子节点的下标除以二得到的是父节点的下标

1.2 数组的存放顺序刚好是层序遍历顺序

1.3 从1开始存储,节点的下标i和结点总数n如果满足 i*2>n说明该结点是叶子结点

2. 思路:

2.1 从最右边的叶子结点开始,对每个叶子结点找到祖先,并把祖先插入向量的首个位置,直到根节点停止

最右边的叶子节点如何找?未必是下标最大的那个,是层数(使用getLayer函数)更小且下标最大的那个(体现在排序函数cmp中)

2.2 判断首个序列是非递增(最大堆)还是非递减,对于后面的每个序列都判断(使用judgeType函数),看是否和首个序列的结论一致,如果有一个不一致,说明这棵树不是堆

3. 纠偏

按照以上思路提交代码上去,得分26/30,这才反应过来自己的判断是什么堆还一个个序列去判断,也太被带沟里了。改成直接写一个判断最大堆、一个判断最小堆的函数,把整棵树当作一个整体来判断,还避免了遇到等号算谁的这种尴尬问题。于是AC。

代码

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<vector>
#include<string>
#include<queue>
#include<map>
#include<cstring>
#include<set>using namespace std;const int maxn = 1010;
const int SUP = 100000010;int n,A[maxn];struct Node{vector<int> preVi;int layer;int idx;
};Node node[maxn];bool cmp(Node a,Node b){return a.layer!=b.layer?a.layer<b.layer:a.idx>b.idx;
}int getLayer(int idx){int k;for(k=0;k<10;k++){if(idx>pow(2,k)-1&&idx<=pow(2,k+1)-1)break;}return k;
}bool isMaxHeap(){for(int i=1;i*2<=n;i++){//对于每一个非叶子结点,判断其和左右节点的大小关系 if(A[i]<A[i*2])return false;if(i*2+1<=n&&A[i]<A[i*2+1])return false;}return true;
}bool isMinHeap(){for(int i=1;i*2<=n;i++){if(A[i]>A[i*2])return false;if(i*2+1<=n&&A[i]>A[i*2+1])return false;}return true;
} int main(){scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&A[i]);}int viNum = 0;//向量的个数 for(int i=n;2*i>n;i--){vector<int> vi;for(int j=i;j>=1;j/=2){vi.insert(vi.begin(),A[j]);}node[viNum].preVi = vi;node[viNum].idx = i;node[viNum].layer = getLayer(i);viNum++;}sort(node,node+viNum,cmp);for(int i=0;i<viNum;i++){for(int j=0;j<node[i].preVi.size();j++){printf("%d",node[i].preVi[j]);if(j!=node[i].preVi.size()-1)printf(" ");}printf("\n");   }if(isMaxHeap())printf("Max Heap\n");else if(isMinHeap())printf("Min Heap\n");else printf("Not Heap\n");return 0;
}

递归解法

DFS解法我参考了柳婼仙女的,她说这个是一个先序的镜像问题,也就是先序遍历是父,左子,右子,而这题是要父,右子,左子。

递归的边界是当前结点已经是叶子结点,即满足下标*2>n(这里无需判断右结点了) 。

另外一个收获是,对于最大最小堆的判断,可以用一种否定法的思想,先假设最大和最小堆都成立,对于每一个有父节点的结点,判断其和父节点的关系。代码简洁很多。

AC代码

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<queue>
#include<string>
#include<map>
#include<vector>
#include<set>using namespace std;const int maxn = 1001;int n;
int A[maxn];
vector<int> vi;void DFS(int root){if(root*2>n){if(root<=n){for(int i=0;i<vi.size();i++){printf("%d%s",vi[i],i==vi.size()-1?"\n":" ");    }}}else{vi.push_back(A[root*2+1]);DFS(root*2+1);vi.pop_back();vi.push_back(A[root*2]);DFS(root*2);vi.pop_back();      }
}int main(){cin>>n;for(int i=1;i<=n;i++){cin>>A[i];}bool isMaxHeap = true,isMinHeap = true;vi.push_back(A[1]);DFS(1);for(int i=2;i<=n;i++){if(A[i]>A[i/2])isMaxHeap = false;if(A[i]<A[i/2])isMinHeap = false;}if(isMaxHeap)printf("Max Heap\n");else{if(isMinHeap)printf("Min Heap\n");else printf("Not Heap\n");}return 0;
}

PAT(甲级)2018年冬季考试 7-4 Heap Paths(非递归与递归解法)相关推荐

  1. 【PAT甲级】2020冬季 PAT 甲级

    2020冬季 PAT 甲级记录 第一次参加PAT,本来九月份报名的时候是打算到十二月份的时候把乙级的题库刷完,然后甲级的题库刷一半,结果因为各种各样的事情(主要是懒又没坚持0.0)这次直到考前乙级才刷 ...

  2. PAT甲级1115 Counting Nodes in a BST (30分):[C++题解] 递归建二叉搜索树、dfs求一层结点数量

    文章目录 题目分析 题目链接 题目分析 分析 首先本题给定的二叉搜索树的定义和其他地方的不同.本题小于等于的是左子树,右子树是大于根结点的. 然后说一下做题的思路. 给定一串数据,让构造二叉搜索树. ...

  3. PAT甲级1102 Invert a Binary Tree:[C++题解]反转二叉树、递归

    文章目录 题目分析 题目链接 题目分析 反转二叉树这道题目特别出名!!!,是因为Homebrew这款Mac上大火的软件的作者到google面试,就考了这道题.面试官说了下面这段话:你竟然连在白板上翻转 ...

  4. PAT(甲级)2018年冬季考试 7-2 Decode Registration Card of PAT

    目录 体会 代码(非满分) 改进 AC代码 体会 这题主要是考察对STL中string,map,vector的应用以及自定义sort()应用. 类型1和2的处理很容易. 类型3要求对于指定date,按 ...

  5. PAT(甲级)2018年冬季考试 7-3 Vertex Coloring

    1. 起先我的思路是,对于每一种方案,把相同颜色的下标放到一个集合,对于每一个集合判断里面的元素互相之间是否有着邻接关系.有一个用例超时,20/25. 2. 转变思路,对于每一种方案,遍历邻接关系,看 ...

  6. PAT(甲级)2018年冬季考试 7-1 Google Recruitment

    1. 本题是 substr+sscanf的绝佳实践. 2. 判断素数使用i*i<=n与i<=(int)sqrt(0.1*x)的区别是前者可能再n接近10的9次方时溢出,但本题不会. 3. ...

  7. 【PAT】2021年冬季考试甲级,摸鱼游记、92分

    T1,简单模拟,20/20分 #include<bits/stdc++.h> using namespace std; const int maxn = 1e5+10; int a[max ...

  8. 记PAT 甲级 2021年 秋季考试 经验总结、线上考试细节、考场题解

    1.简单回顾 今天下午考完了秋季的考试,最终得了97分,第一题扣了3分,非常遗憾.还有一个多小时的时候就已经97了,回来和第一题的剩余3分周旋到最后,没能发现问题所在,不停考虑各种,我觉得可能是陷在已 ...

  9. PAT甲级 2019年冬季 题解

    题目1:7-1 Good in C (20分) When your interviewer asks you to write "Hello World" using C, can ...

最新文章

  1. user is not in the sudoers file.
  2. python mysql append_Python细节——MYSQL的to_sql的if_exists推荐使用append
  3. canvas-应用大全
  4. Android常见面试题(一)
  5. OpenCASCADE绘制测试线束:检查器命令之Inspector
  6. 5年程序员生涯,使用的最频繁的Git 命令总结
  7. Nmon 性能:分析 AIX 和 Linux 性能的免费工具
  8. # javascript 总结
  9. VS2008(C#)子页嵌套母版页的控件访问方法(二)
  10. Android -- 开机启动无界面后台程序
  11. JBOSS5+ActiveMQ5.7集成
  12. 调用登录_微信小程序登录那些事
  13. 校园卡系统mysql与java结合_基于Java+JSP+Mysq+Servletl的校园卡一卡通管理系统
  14. JS纯前端导出PDF及分页和使用window.print()保存PDF
  15. Colab 修改工作路径
  16. java 图片实现毛玻璃_iOS毛玻璃效果的实现及图片模糊效果的三种方法
  17. ROS小车基于yocs_smoother_velocity做速度平滑处理
  18. PCI GXL 关于JPS与作业
  19. 车牌对应城市行政区编号
  20. STM32F407定时器输入捕获

热门文章

  1. iOS开发系列--让你的应用“动”起来
  2. h5 getUserMedia error PermissionDeniedError
  3. Codeforces Round #270
  4. 论排列组合,持续更新
  5. jquery autocomplete实现solr查询字段自动填充并执行查询
  6. xp/2003开关3389指令
  7. 不要一辈子靠技术生存
  8. 扫码下单支持同桌单人点餐FAQ
  9. SQLServer之DEFAULT约束
  10. Intel或将裁员数千人 谋求业务转型