蓝桥杯2020年真题:BST插入节点问题

题目

时间限制: 1.0s 内存限制: 512.0MB 本题总分:25 分
【问题描述】 
给定一棵包含 N 个节点的二叉树,节点编号是 1 ∼ N。
其中 i 号节点具有 权值 Wi,并且这些节点的权值恰好形成了一棵排序二叉树 (BST)。 
现在给定一个节点编号 K,小明想知道,在这 N 个权值以外,
有多少个整 数 X (即 X 不等于任何 Wi ) 满足:
给编号为 K 的节点增加一个权值为 X 的子 节点,仍可以得到一棵 BST。 
例如在下图中,括号外的数字表示编号、括号内的数字表示权值。
即编号 14 的节点权值依次是 0102030

在这里插入图片描述

如果 K = 1,那么答案为 0。因为 1 号节点已经有左右子节点,不能再增 加子节点了。 
如果 K = 2,那么答案为无穷多。因为任何一个负数都可以作为 2 的左子 节点。 
如果 K = 3,那么答案为 9。因为 X = 11,12,··· ,19 都可以作为 3 的左子 节点。
【输入格式】
第一行包含 2 个整数 N 和 K。 以下 N 行每行包含 2 个整数,
其中第 i 行是编号为 i 的节点的父节点编号 Pi 和权值 Wi 。
注意 Pi = 0 表示 i 是根节点。 
输入保证是一棵 BST。
【输出格式】 
一个整数代表答案。如果答案是无穷多,输出 −1。
【样例输入】 
4 3 
0 10 
1 0 
1 20 
3 30
【样例输出】 
9
【评测用例规模与约定】 
对于 60% 的评测用例,1≤ K ≤ N ≤1000≤Wi ≤200,且 Wi 各不相同。 
对于所有评测用例,1 ≤ K ≤ N ≤ 100000 ≤ Wi ≤ 100000000,且 Wi 各不 相同。

答案

不知道对错(感觉没问题),而且代码有点长,因为时间问题,就没有将代码抽取出来缩短了
如果是超时的忧虑的话,我觉得不会超时,我们寻找节点的时间复杂度是logN
而且最多我们只需要寻找两个节点就可以了
package competition4;

import java.util.Scanner;

public class InsertBST
{
    
    
//	public static int N,K;
//	public static int[][] arr;
//	public static void main(String[] args)
//	{
    
    
//		Scanner in = new Scanner(System.in);
//		N=in.nextInt();
//		K=in.nextInt();
//		arr=new int[N+1][2];
//		for(int x=1;x<arr.length;x++)
//		{
    
    
//			for(int y=0;y<arr[x].length;y++)
//			{
    
    
//				arr[x][y]=in.nextInt();
//			}
//		}
//		in.close();
		/*
		 * (错误的)
		 * 思路大概这样:
		 * 首先父节点挺容易找的,难找的就是孩子节点,
		 * 我看了一下N的数据量只达到10的四次方,
		 * 所以直接暴力找它有没有孩子节点,
		 * 如果有两个孩子节点就返回0
		 * 如果都没有孩子节点,这就麻烦点了:
		 * 		就要找这个节点的父节点:还要判断是父节点的左子节点还是右子节点
		 * 		还要找这个节点的父父节点:还有判断是父父节点的左子节点还是右子节点
		 * 		然后根据父节点和父父节点的值就可以判断范围了
		 * 如果是只有一个节点:
		 * 		这会也像上面那样,不过区别是不用找父节点和父父节点了
		 * 		而是直接找当前节点和父节点就行了
		 * 		(思路到这里我就发现了事情的严重性,不能这样写,
		 * 		还是得乖乖建立二叉树,因为有可能要找到很多次父节点才能找到范围
		 * 		比如根节点1的左孩子2,然后2的右孩子3,3的右孩子4,4的右孩子5
		 * 		k是5的话就要找到根节点1才能确定范围
		 */
		
//	}
	public static int N,K;
	public static int[][] arr;
	public static void main(String[] args)
	{
    
    
		Scanner in = new Scanner(System.in);
		N=in.nextInt();
		K=in.nextInt();
		arr=new int[N+1][2];
		for(int x=1;x<arr.length;x++)
		{
    
    
			for(int y=0;y<arr[x].length;y++)
			{
    
    
				arr[x][y]=in.nextInt();
			}
		}
		in.close();
		//建立好这棵树的每一个节点
		BinaryNode[] nodes=new BinaryNode[N+1];
		for(int x=1;x<arr.length;x++)
		{
    
    
			nodes[x]=new BinaryNode(arr[x][1], x);
		}
		//建立好这棵树
		for(int x=1;x<arr.length;x++)
		{
    
    
			if(arr[x][0]!=0)
			{
    
    
				//如果父节点的权重大于当前节点的,就是左孩子
				if(nodes[arr[x][0]].weight>nodes[x].weight)
				{
    
    
					nodes[arr[x][0]].l=nodes[x];
				}
				else
				{
    
    
					nodes[arr[x][0]].r=nodes[x];
				}
			}
		}
		//获取第K个节点
		BinaryNode temp=nodes[K];
		//如果这个节点已经存在左右节点了,那就莫得办法
		if(temp.l!=null && temp.r!=null)
		{
    
    
			System.out.println("-1");
			return;
		}
		//如果有左子树,那么右子树还能加入
		if(temp.l!=null && temp.r==null)
		{
    
    
			/*
			 * 现在是想向上找当前节点的父节点,
			 * 现在如果当前节点是父节点的左孩子,就可以不找了,
			 * 		因为确定范围是父节点权重到当前节点权重的值
			 * 如果当前节点是父节点的右孩子,就一直找,直到找到左孩子的出现
			 * 		范围是父节点权重到当前节点权重的值
			 * 如果找到根节点还找不到,就是无穷大了
			 */
			//保存当前节点的权重
			int start=temp.weight;
			while(nodes[arr[K][0]].r==temp && K!=1)
			{
    
    
				temp=nodes[arr[K][0]];
				K=temp.id;
			}
			if(K==1)
			{
    
    
				System.out.println("-1");
				return;
			}
			else
			{
    
    
				System.out.println(nodes[arr[K][0]].weight-start-1);
			}
			
		}
		//如果有右子树,那么左子树还能加入,方法和上面类似
		if(temp.r!=null && temp.l==null)
		{
    
    
			int start=temp.weight;
			while(nodes[arr[K][0]].l==temp && K!=1)
			{
    
    
				temp=nodes[arr[K][0]];
				K=temp.id;
			}
			if(K==1)
			{
    
    
				System.out.println("-1");
				return;
			}
			else
			{
    
    
				System.out.println(start-nodes[arr[K][0]].weight-1);
				return;
			}
		}
		//两个都没有就上面两个的结合情况,方法和上面大同小异(我也是从上面复制的)
		if(temp.r==null && temp.l==null)
		{
    
    
			int start=temp.weight;
			if(K==1)
			{
    
    
				System.out.println("-1");
				return;
			}
			//证明当前节点是父节点左孩子,然后就一直向上找,找到父节点的右孩子
			if(nodes[arr[K][0]].l==temp && K!=1)
			{
    
    
				temp=nodes[arr[K][0]];
				K=temp.id;
				while(nodes[arr[K][0]].l==temp && K!=1)
				{
    
    
					temp=nodes[arr[K][0]];
					K=temp.id;
				}
				if(K==1)
				{
    
    
					System.out.println("-1");
					return;
				}
				else
				{
    
    
					System.out.println(start-nodes[arr[K][0]].weight-1);
					return;
				}
			}
			else
			{
    
    
				temp=nodes[arr[K][0]];
				K=temp.id;
				while(nodes[arr[K][0]].r==temp && K!=1)
				{
    
    
					temp=nodes[arr[K][0]];
					K=temp.id;
				}
				if(K==1)
				{
    
    
					System.out.println("-1");
					return;
				}
				else
				{
    
    
					System.out.println(nodes[arr[K][0]].weight-start-1);
				}
			}
		}
	}
}
class BinaryNode
{
    
    
	int id;
	BinaryNode r;
	BinaryNode l;
	int weight;
	public BinaryNode(int weight,int id)
	{
    
    
		this.weight = weight;
		this.id = id;
	}
}

猜你喜欢

转载自blog.csdn.net/qq_43416157/article/details/109006228