蓝桥杯刷题——2021真题“双向排序”(JAVA)
记录一下我遇到的超时问题、报错问题的解决方案。
首先这里给出题目:
题目分析:
这道题目让我们对给定长度的数组进行排序,要求是如果给定的pi=0,则把原数组的1-qi按照降序排列,如果给定的pi=1,则把原数组的qi到n按照升序排列。
这么说来就很简单了,不就是排序吗,只要确定了每个步骤的pi(按照升序排列还是降序排列),在根据具体需要排序的内容即由qi确定的序列,再利用一种排序算法,随便套上去不就完了吗。而我最近不是刚刚复习了快排吗,这个闭着眼睛就能写出的算法,稍稍改一下(两个大于小于互换即可)就可以把升序变为降序,那不太简单了吗。
于是我开始了我漫长的尝试......
首先我们需要写一个主函数,并读取从键盘输入的各类数据:jiejie
public static void main (String[] args) {Scanner scanner = new Scanner(System.in);int n=scanner.nextInt();int m=scanner.nextInt();int pi[] = new int[m];int qi[] = new int[m];int a[] = new int[n];for(int i=0;i<m;i++) {pi[i]=scanner.nextInt();qi[i]=scanner.nextInt();}
接着对数组赋初值:
for(int i=0;i<n;i++) {a[i]=i+1;}
然后我们需要编写按照升序排列的快速排序算法以及按照降序排列的快速排序算法。这里可以参考我的另一篇博客:
蓝桥杯算法复习——快排_拉姆哥的小屋的博客-CSDN博客
代码如下(按照升序排列):
public static int[] quickSort_1(int[] a,int low,int high) {int left=low;int right=high;if(left<right) {int temp=a[low];while(left!=right) {while(left=temp) {right--;}a[left] = a[right];while(left<right&&a[left]<=temp) {left++;}a[right] = a[left];}a[left] = temp;quickSort_1(a, low, left-1);quickSort_1(a, left+1, high);}return a;}
代码(按照降序排列):
public static int[] quickSort_0(int[] a,int low,int high) {int left=low;int right=high;if(left<right) {int temp=a[low];while(left!=right) {while(left<right&&a[right]<=temp) {right--;}a[left] = a[right];while(left=temp) {left++;}a[right] = a[left];}a[left] = temp;quickSort_0(a, low, left-1);quickSort_0(a, left+1, high);}return a;}
最后需要编写主函数中的判断和打印部分:
for(int i=0;i<m;i++) {if(pi[i]==0) {a=quickSort_0(a,0,qi[i]-1);}else {a=quickSort_1(a,qi[i]-1,n-1);}}for(int j=0;j<n;j++) {System.out.print(a[j]+" ");}
最后我们进入蓝桥杯练习系统提交代码:
奇了怪了,怎么会这样,快排都满足不了了吗?难道是?
所以我们继续思考,查阅资料,发现:蓝桥杯很多时候不是光靠优质的基础算法就可以解决的,我们需要观察发现题目中的规律,简化的不是算法本身,而是一些处理过程。
最后,经过我们的努力,完整的代码如下(满分):
import java.util.*;class Main{public static class pair{int x=0;int y=0;pair(int a,int b) {x=a;y=b;}}public static void main(String args[]) {int n,m;Scanner scan=new Scanner(System.in);n=scan.nextInt();m=scan.nextInt();pair[] pairs= new pair[n+1];int top=0;int item[]=new int[n+1];//for(int i=1;i<=n;i++) {//item[i]=i;//}int p,q;for(int i=0;i0) {//top大于0是为了保证第一次操作为 0操作while(top>0&&pairs[top].x==1) {//top记录上一个操作//若连续出现相同的操作,取范围大的那个if(pairs[top].y=2&&pairs[top-1].y>=q) {top-=2;//删除一组操作(即0操作和1操作)}pairs[++top]=new pair(1,q);//top始终停留在要记录操作的前一步//System.out.println("top: "+top+" 操作1 x: "+pairs[top].x+" y: "+pairs[top].y);}if(p==0){while(top>0&&pairs[top].x==0) {if(pairs[top].y>=q)q=pairs[top].y;--top;}while(top>=2&&pairs[top-1].y<=q)//若不加=,会存两次相同的值top-=2;pairs[++top]=new pair(0,q); //System.out.println("top: "+top+" 操作0 x: "+pairs[top].x+" y: "+pairs[top].y);}}int k=n;int l=1,r=n;for(int i=1;i<=top;i++) {if(pairs[i].x==0) {while(l<=r&&pairs[i].y<r)item[r--]=k--;}if(pairs[i].x==1) {while(ll)item[l++]=k--;}}if(top%2==0) {//为操作1while(l<=r)item[r--]=k--;}else {//为操作0while(l<=r)item[l++]=k--;}for(int i=1;i<=n;i++) {System.out.print(item[i]+" ");}}}
喜欢的小伙伴点赞加关注哦!