题意:
给定一棵完全二叉树按照层次遍历的访问序列,对于这棵树的每条边,所表示的价值为这条边两点序号的异或值,求出整棵树所有边的价值和。
解法一(记录父节点)
我们用一个变量表示当前枚举到的节点下标(从左到右枚举),从开始枚举
用一个变量表示当前下标为所代表的节点的父亲节点的下标,显然刚开始为
如下图:
我们的变量是从左到右枚举的,变量显然也是从左到右枚举
我们发现,变量每枚举了两个节点,变量刚好枚举了一个节点
于是我们可以记录下当前已经访问了多少个节点,每访问两个节点后让变量加上
于是我们就做完了
代码:
class Solution { public: long long tree1(vector<int>& a) { long long ans=0; for(int i=1,j=0,c=0;i<a.size();i++){ //i为当前节点,j为当前节点父节点 //c为从第二个开始已经访问的节点个数 c++; ans+=a[i]^a[j]; if(c%2==0)j++;//每访问两个加一次 } return ans; } };时间复杂度:,程序中循环体执行了次,循环体中的时间复杂度是的,故总的时间复杂度为
空间复杂度:,程序中存储了一个有个整型元素的数组,还有若干个整型或长整型变量,故总的空间复杂度为
解法二(找节点下标规律):
我们观察如下完全二叉树(编号从开始)
我们很容易发现,若当前节点编号为,则当前节点的左儿子编号为,当前节点的右儿子编号为
但是题目中的数组下标是从开始的,我们可以把所有的计算完后的编号整体向左移动一位
于是我们就做完了(注意判断超界)
代码:
class Solution { public: long long tree1(vector<int>& a) { long long ans=0; for(int k=1;k<=a.size();k++){ //k为当前节点 if(k*2-1<a.size()){//左儿子 ans+=a[k-1]^a[k*2-1]; } if(k*2+1-1<a.size()){//右儿子 ans+=a[k-1]^a[k*2+1-1]; } } return ans; } };时间复杂度:,程序中循环体共执行了次,循环体内部的时间复杂度是的,故总的时间复杂度是
空间复杂度:,程序中存储了一个有个整型元素的数组,还有若干个整型或长整型变量,故总的空间复杂度为