试题 算法训练 区间k大数查询(Java)
方法:排序、查找
题目
资源限制
时间限制:1.0s
内存限制:256.0MB
问题描述
给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个。
输入格式
第一行包含一个数n,表示序列长度。
第二行包含n个正整数,表示给定的序列。
第三个包含一个正整数m,表示询问个数。
接下来m行,每行三个数l,r,K,表示询问序列从左往右第l个数到第r个数中,从大往小第K大的数是哪个。序列元素从1开始标号。
输出格式
总共输出m行,每行一个数,表示询问的答案。
样例输入
5
1 2 3 4 5
2
1 5 2
2 3 2
样例输出
4
2
数据规模与约定
对于30%的数据,n,m<=100;
对于100%的数据,n,m<=1000;
保证k<=(r-l+1),序列中的数<=106。
分析:
一开始看到这道题的时候我还是不会的,最后思索了很久才发现,这个可以使用二维数组进行解决,然后就尝试了几次,然后接解决了这个事情,接下来我分享一下,我在做这道题的时候的一些分析思路,希望能够带给一些没有思路的朋友一些灵感。
1.第一步先利用一维数组int arr[ ] = new int [n]将数据录入。
2.再创建一个一维数组 int arr [ ] = new int [m],录入我们要寻找的第几大数字 k 。创建一个二维数组int arr1 [ ] [ ]= new int [m] [1000] ,然后,利用循环,将一维数组中的 l 到 r 的之间的这几位数字录入到二维数组中,输入的m是多少,就录入多少次,每次对应的数字和数目都是 l 和 r 对应的那些数字。
3.现在,我们已经创建了m 行,每列不一定相等的二维数组。现在对这个二维数组的每一行进行排列,调用方法Arrays.sort()进行排序,当然这个是从小到大排序的(因为我之前用了冒泡法和其他方法,结果失败了,然后就只能用这个方法,然后再反向调用,也可以正常输出),因为之前,我给这个二维数组创建了m行,1000列,在这1000列里面除了有效值外,其他的值都是默认值0,如果从小到大排列了之后,那前面都是0,从索引999往前数字逐渐减小。因此,利用循环,从后往前找这个第K大的数字,获取arrk[i]里面的数值,来寻找这个数字,如果是第一大数字,那就是输出的是arr[i] [999],第二大数字,就是arr1[i] [998],这样我们通过分析,可以知道,这个最终的数字就是1000-k,即就是1000-arrk[i]。
4.最后,输出结果,完成了这道题。
代码如下:
import java.util.Scanner;
import java.util.Arrays;
class Main{
public static void main(String [] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int arr[] = new int [n];
for (int i = 0 ; i < arr.length; i ++){
arr[i] = sc.nextInt();
}
int m = sc.nextInt();
int arrk[] = new int [m];
int arr1[][] = new int[m][1000];
for(int i = 0; i < m; i ++){
int l = sc.nextInt();
int r = sc.nextInt();
int k = sc.nextInt();
int temp = 0;
for(int j = l-1; j < r; j++){
arr1[i][temp++] = arr[j];
}
arrk[i]= k;
}
for(int i = 0; i < m ; i ++){
for(int j = 0; j < arr1[i].length; j++){
arr1[i][j] = arr1[i][j];
}
}
int te = 0;
for(int i = 0 ; i < m ; i ++){
Arrays.sort(arr1[i]);
}
for(int i = 0;i < m ; i ++){
int z = arrk[i] ;
int y = 1000 -z;
System.out.println(arr1[i][y]);
}
}
}