Blue Bridge Cup [real exercise] weight of complete binary tree

Posted by fluvius on Thu, 10 Feb 2022 14:52:25 +0100

[problem description]

Given a complete binary tree with N nodes, each node in the tree has a weight, which is A1, A2, ···· AN from top to bottom and from left to right, as shown in the following figure:

Now Xiao Ming wants to add up the weights of nodes with the same depth. He wants to know which depth has the largest sum of nodes' weights? If the weight sum of multiple depths is the largest, please output the smallest depth.

Note: the depth of the root is 1.

[input format]

The first line contains an integer N.
The second line contains N integers A1, A2, ··· AN.

[output format]

Output an integer representing the answer.

[sample input]

7
1 6 5 4 3 2 1

[sample output]

2

[evaluation case scale and agreement]

For all evaluation cases, 1 ≤ N ≤ 100000, − 100000 ≤ Ai ≤ 100000.

Train of thought 1

This topic focuses on the properties of binary tree, which has little to do with the storage structure of binary tree.

It can be seen from the analysis above that when the number of layers is j, the address of each layer element in the array is in the interval [2 ^ (J-1), 2 ^ J), which is the core point

Then sum and compare the elements of each layer to get the number of layers where the maximum sum of weights is located. Since it is calculated from the first layer from bottom to top, there is no need to update the number of layers when the sum of weights of a certain layer is the same as that of the current layer. At this time, the depth of the current layer is the smallest.

Code 1

The relevant functions in < cmath > are used in the code. The summary of common functions is as follows:

Function nameFunction description
floor (x)Round down, that is, the largest integer not greater than x
ceil(x)Round up, that is, the smallest integer not less than x
pow(x,y)Power function, that is, calculate the y-power of x
sqrt(x)The square function is to find the square root of x
round(x)Rounding function, that is, rounding x to get the nearest integer
log(x)Logarithmic function, that is to find the logarithm of x with e as the base, which is usually calculated by the bottom exchange formula
#include<iostream>
#include<cmath>
using namespace std;
const int N = 100005;
long long a[N]={0};
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];//The subscript starts from 1 and is consistent with the sequence number of the complete binary tree, which is convenient for operation 
	} 
	long max=0,sum=0;
	int i,j,depth=0;
	for(i=1;i<=floor(log(n)/log(2))+1;i++){//floor() is a downward rounding function 
		sum=0;
		for(j=pow(2,i-1);j<pow(2,i);j++){
			sum+=a[j];
			if(j==n)break;//It indicates that the operation has reached the last node. Jump out of the inner loop first 
		}
		if(sum>max){
			max=sum;
			depth=i;
		}
		if(j==n)break;//Then jump out of the outer loop and the calculation is over 
	}
	cout<<depth;
	return 0;
}

Train of thought 2

Idea 1 is to use the depth to find the address range of each layer element in the array, and then accumulate and compare

Idea 2 is to set the "move" variable pos in the array, and the moving distance is the number of elements in each layer

It should be noted that it is necessary to judge whether it is a full binary tree. Because the graph in the topic is confusing to some extent, a complete binary tree is not necessarily a full binary tree. Therefore, it is necessary to compare the number of elements in the last layer with the maximum number of elements in that layer. If it is equal, it is a full binary tree, and if it is less than, it is a non full binary tree.

Code 2

#include<iostream>
#include<cmath>
using namespace std;
const int N = 100005;
long long a[N]={0};
int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
	} 
	int deep=1,pos=0;
	long long max=0;
	int depth=floor(log(n)/log(2))+1;//Depth of complete binary tree with n nodes 
	for(int i=1;i<=depth;i++){
		long long sum=0;
		int node=pow(2,i-1);//The maximum number of nodes on the i-th layer 
		//Non full binary tree 
		int temp=n-pos;//You must first save the value of n-pos, because POS is constantly moving and changing 
		if(temp<node){
			for(int j=0;j<temp;j++){
				sum+=a[pos++];
			}
		} 
		//Full binary tree 
		else{
			for(int j=0;j<node;j++){
				sum+=a[pos++];
			}
		}
		if(sum>max){
			max=sum;
			deep=i;
		}
	}
	cout<<deep<<endl;
	return 0;
}

summary

Idea 2: when performing operations related to the non full binary tree, I made a detailed error in the code at the beginning, that is, I didn't save the value of n-pos, and then directly performed the following operations. Because POS is constantly moving and changing, the n-pos is also changing, and what we want is to determine the non full binary tree based on the value of n-pos at the beginning of the operation. This is also the reason why the 10 test points have failed all the time!

Error code:

Correct code:

After discovering it, I now feel that this is a small problem that is not fully considered, but I have been looking for it for a long time. As a result, I asked my friends to help me see it and found the reason in five minutes. It is really the so-called "those who are in the game and those who are on the sidelines are clear", so I must be more rigorous in dealing with some small details in the future! Faster, but more accurate.

Topics: C++ data structure