P5076 【深基16.例7】普通二叉树(Java语言实现)

 题目难度:普及+/提高

题目描述

您需要写一种数据结构,来维护一些数( 都是 10^9 以内的数字)的集合,最开始时集合是空的。其中需要提供以下操作,操作次数 q 不超过 10^4:

  1. 查询 x 数的排名(排名定义为比当前数小的数的个数 +1。若有多个相同的数,应输出最小的排名)。
  2. 查询排名为 xx的数。
  3. 求 x 的前驱(前驱定义为小于 x,且最大的数)。若未找到则输出 -2147483647。
  4. 求 x 的后继(后继定义为大于 x,且最小的数)。若未找到则输出 2147483647。
  5. 插入一个数 x。

输入输出样例

输入

7
5 1
5 3
5 5
1 3
2 2
3 3
4 3

输出:

2
3
1
5

思路:

用链表+二分答案来解决,链表(LinkedList类)来储存数据,这个类基本内置了链表的所有方法。先插入两个元素-2147483647,2147483647作为链表的下界与上界,在查询的时候可以防止链表越界,在插入元素的过程中可以先用二分答案来查找应该插入的位置,再调用Linkedlist类的add方法直接在该位置添加元素,该位置后面元素会自动后移,

求x的前驱后继也能用二分答案来解决。

同时注意理解题意,x可能是不存在于链表中的。

注意二分答案用法,需要厘清如何求满足目标条件的最大值,或者满足目标条件的最小值。

AC代码

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeSet;

public class Main {
	static List<Integer> list=new LinkedList<>();
	static int size=2;
	public static void main(String[] args) throws Exception{
		PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));//快速输出	
		Read read=new Read();//快读
		int n=read.nextInt();
		list.add(-2147483647);//添加上界与下界
		list.add(2147483647);
		while(n-->0) {
			int op=read.nextInt();
			int num=read.nextInt();
			switch (op) {
			case 1: {
				out.println(lower(num)+1);//注意,num可能不存在,所以要找到比num小的数中最大的一个的下标,再+1;
				break;
			}
			case 2:{
				out.println(list.get(num));
				break;
			}
			case 3:{
				int index=lower(num);
				out.println(list.get(index));
				break;
			}
			case 4:{
				int index=higher(num);//二分答案
				out.println(list.get(index));
				break;
			}
			case 5:{
				int index=higher(num);	//二分答案
				list.add(index, num);;
				size++;
				break;
			}
			}
		}

		out.flush();
		
	}
//二分答案:查找小于目标数的最大数的下标, 例如 1 2 4 5 ,target为3,小于target的最大的数为2。
	static int lower(int target) {
		int left=0;
		int right=size-1;
		while(left<right) {
			int mid=(left+right)/2;
			if(list.get(mid)>=target)
				right=mid;
			else {
				left=mid+1;
			}
		}
		return left-1;
	}
	//二分答案,查找大于目标数的的最小的一个。
	static int higher(int target){
		int left=0;
		int right=size-1;
		while(left<right) {
			int mid=(left+right)/2+1;
			if(list.get(mid)<=target) {
				left=mid;
			}
			else {
				right=mid-1;
			}
		}
		return left+1;
	}
}
class Read{
	StreamTokenizer st=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	public int nextInt() throws Exception{
		st.nextToken();
		return (int)st.nval;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Z菌君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值