PREV-7连号区间数(Java)详解
前言
读了半天题,没明白啥是连号区间,又没一个样例,后来才知道,拿第一个输入样例来说,[1,1],[1,2],[1,3],[1,4],[2,2],[3,3],[4,4]这7个就叫连号区间,分别对应的是[3],[3,2],[3,2,4],[3,2,1,4],[2],[4],[1].可能是语文水平太差了.下面给出两份代码,一份是自己的想法只能得80分,一份是蓝桥真题讲解视频中的.
问题描述
小明这些天一直在思考这样一个奇怪而有趣的问题:
在1~N的某个全排列中有多少个连号区间呢?这里所说的连号区间的定义是:
如果区间[L, R] 里的所有元素(即此排列的第L个到第R个元素)递增排序后能得到一个长度为R-L+1的“连续”数列,则称这个区间连号区间。
当N很小的时候,小明可以很快地算出答案,但是当N变大的时候,问题就不是那么简单了,现在小明需要你的帮助。
输入格式
第一行是一个正整数N (1 <= N <= 50000), 表示全排列的规模。
第二行是N个不同的数字Pi(1 <= Pi <= N), 表示这N个数字的某一全排列。
输出格式
输出一个整数,表示不同连号区间的数目。
样例输入1
4
3 2 4 1
样例输出1
7
样例输入2
5
3 4 2 5 1
样例输出2
9
代码1(自己的想法,只能得80分)
import java.util.Arrays;
import java.util.Scanner;
//想法是将每个区间取到新的数组里继续判断是不是连号区间
public class PREV_7 {
/**
* @param args
*/
static int answer=0;
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int num[]=new int[n];
for(int i=0;i<n;i++){
num[i]=sc.nextInt();
}
for(int i=0;i<n;i++){//新数组的第一个数,即左区间对应的数字
int j=1;//其中最少也要有一个数
while(j<=n-i){//j最大不能超过数组中的剩余数
solve(num,j,i);
j++;
}
}
System.out.println(answer);
}
/*
* num[]原始数组,用于从中取数据到新数组
* count新数组的大小,从原始数组中提取数据的次数
* n开始提取的下标
*/
private static void solve(int []num,int count,int n){
int m[]=new int [count];
for(int i=0,j=n;i<count;i++){
m[i]=num[j];//将原始数组中的数,转移到新数组中,便于判断给区间是不是连号区间
}
Arrays.sort(m);
if(m[m.length-1]-m[0]==count-1)//满足题意的递增序列一定是最大数减最小值等于区间中个数减1
answer++;
return ;
}
}
代码2(能够AC)
import java.util.Scanner;
public class PREV_7 {
/**
* @param args
*/
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int num[]=new int[n+1];
for(int i=1;i<=n;i++){
num[i]=sc.nextInt();
}
int answer=0;
for(int i=1;i<=n;i++){//左区间
int max=num[i];
int min=num[i];
for(int j=i;j<=n;j++){//右区间
//循环结束后,max是该区间的最大值,min是该区间的最小值
if(num[j]>max)max=num[j];
if(num[j]<min)min=num[j];
if(i==j){//区间中只有一个数的时候
answer++;
}else{//j>i
if(max-min==j-i)answer++;//满足题意的递增序列一定是最大数减最小值等于右区间的下标数-左区间的下标数
}
}
}
System.out.println(answer);
}
}
总结
自己的思维还是太局限了,既比人家的麻烦又不能全部通过,最后一个很大的数,就运行超时了,还是太菜了.呜呜呜