0
点赞
收藏
分享

微信扫一扫

AcWing 789. 数的范围(Java)

书写经典 2022-01-31 阅读 51

给定一个按照升序排列的长度为 nn 的整数数组,以及 qq 个查询。

对于每个查询,返回一个元素 kk 的起始位置和终止位置(位置从 00 开始计数)。

如果数组中不存在该元素,则返回 -1 -1

输入格式

第一行包含整数 nn 和 qq,表示数组长度和询问个数。

第二行包含 nn 个整数(均在 1∼100001∼10000 范围内),表示完整数组。

接下来 qq 行,每行包含一个整数 kk,表示一个询问元素。

输出格式

共 qq 行,每行包含两个整数,表示所求元素的起始位置和终止位置。

如果数组中不存在该元素,则返回 -1 -1

数据范围

1≤n≤1000001≤n≤100000
1≤q≤100001≤q≤10000
1≤k≤100001≤k≤10000

输入样例:

6 3
1 2 2 3 3 4
3
4
5

输出样例:

3 4
5 5
-1 -1

本题目通过二分算法找出左边界与右边界,最后输出左边界与右边的的值即可。

二分的本质不是单调性, 单调性的题目一定可以二分, 可以二分的题目不一定有单调性

二分的本质是边界
二分法用于查找, 每次都选择答案所在的区间再次进行查找, 当区间长度为 1时, 就是答案

 二分算法模板

	int bsearch_l(int l, int r) {
		while (l < r) {
			int mid = (l + r) / 2;
			if (check[mid]) // check 判断mid是否满足条件
				r = mid;
			else
				l = mid + 1;
		}
		return l;
	}
	int bsearch_r(int l, int r) {
		while (l < r) {
			int mid = (l + r + 1 ) / 2;
			if (check[mid]) // check 判断mid是否满足条件
				r = mid;
			else
				l = mid -1 ;
		}
		return l;
	}

答案代码

import java.util.*;

public class Main{

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner reader = new Scanner(System.in);
		int a = reader.nextInt();
		int b = reader.nextInt();
		int arr[] = new int[a];
		for (int i = 0; i < a; i++) 
			arr[i] = reader.nextInt();
		
		while (b-- != 0) {
		int x = reader.nextInt();
		int l = 0;
		int r = a - 1;
		// 找左边边界
		while (l < r) {
			int mid = l + r >> 1;
			if (arr[mid] >= x) {
				r = mid;
			} else {
				l = mid + 1;
			}
		}
        //若找出的值不是与之前匹配的值,说明没找到,直接输出没找到的结果即可。
		if (arr[l] != x) {
			System.out.println("-1 -1");
		} else {
			System.out.print(l + " ");
			l = 0;
			r = a - 1;
			//找出右边界
			while (l < r) {
				int mid = l + r + 1 >> 2;
				if (arr[mid] <= x)
					l = mid;
				else
					r = mid - 1;
			}
			System.out.println(l);
		}
	}
	}

}

 

举报

相关推荐

0 条评论