完全二叉树的权值

完全二叉树的权值

问题描述:

给定一颗包含N个结点的完全二叉树,每个结点都有一个权值,命名规律如图所示:

**<这里插入二叉树图片>**

现在小明要把相同深度的结点权值加在一起,他想知道哪个深度的结点权值之和最大。如果有多个深度的权值和最大,请你输出其中最小的深度值。根的深度设为1。

输入和输出格式:

输入:

第一行包括一个整数N,表示有N个结点

第二行包含N个整数,代表 A 1 , A 2 , A 3 . . . A n A_{1},A_{2},A_{3}...A_{n} A1,A2,A3...An

输出:

一个整数,代表权值之和最大的深度值

分析:

因为在二叉树中结点权值排列的顺序和输入的顺序刚好是匹配的。

所以要对各个深度的权值进行求和,只需顺序遍历输入数据即可。

值得注意的是:完全二叉树第 n 层的结点个数是: 2 n − 1 2^{n-1} 2n1

此题中,可以首先计算输入N得到的完全二叉树的深度,然后对每个深度进行计算。也可以不用计算深度,只需要计数当前求和了多少个元素,当为N个时,计算完就停止。

如果选择首先计算深度的话,因为二叉树的深度为: c e i l ( l o g 2 ( n + 1 ) ) ceil(log_{2}(n+1)) ceil(log2(n+1)),而C++中的库函数 log求的是以e为底的。因而需要利用对数换底公式来计算:

l o g a b = l o g c b l o g c a l o g 2 x = l n x l n 2 log_{a}b=\frac{log_{c}b}{log_{c}a}\\ log_{2}x=\frac{lnx}{ln2} logab=logcalogcblog2x=ln2lnx

其次,题目要求如果有多个深度的权值都是最大的,那么要输出最小的深度值。因为我们是从第1层开始计算的,所以只需设置第一层的权值和为最大值,只有当下一层的权值和大于当前max时,才更新结果,就可以满足题目要求。

还有一点,因为题目上说每个权值可正可负,所以在设置最初的最大权值和时,要么初始化一个特别小的数,要么就在计算第一层的和时,把权值和赋给最大权值和。这里采用设置一个大负数的方法 (0x3f3f3f3f)。

当我们需要设置一个int类型的最大值以用于某种功能时,首先我们能够想到使用: 0x7f ff ff ff (4字节int类型的最大值),这个值为:2147483647

但是使用这个INF的时候,仅仅做一点运算便会造成溢出。因为为了给INF腾出一点运算的空间:

  • 能够乘2倍不溢出
  • 0x7f ff ff ff 一个数量级

所以使用:0x3f 3f 3f 3f ,也是一个十位数1061109567,乘2也刚好不会溢出。

所以,可以利用 0x3f3f3f3f 来设置一个很大的量,作为界限值或者近似无穷来使用。

代码:
#include<iostream> 
#include<cmath>
#define INF 0x3f3f3f3f
using namespace std;

int num[100007];	//存储输入数据 
 
int main(void){
	
	int N;
	cin>>N;	
	for(int count=0;count<N;count++){
		cin>>num[count];
	}
	int result=1, numIter=0, depSum=0, max=-INF;
	//对每一层求和并进行比较 
	for(int depCount=1;depCount<=ceil(log(N+1)/log(2));depCount++){
		depSum=0;
		for(int temp=0;temp<pow(2,depCount-1);temp++){
			depSum+=num[numIter++];
		}
		if(depSum>max){	//更新最大权值和 
			max=depSum;
			result=depCount;
		}
	}
	cout<<result;

	return(0);
}

如果采取不计算深度的方式的话:

在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值