题目:
小蓝有一个长度为 N 的数组, 初始时从左到右依次是 1,2,3,…N 。
之后小蓝对这个数组进行了 M 次操作, 每次操作可能是以下 2 种之一:
左移 x, 即把 x 移动到最左边。
右移 x, 即把 x 移动到最右边。
请你回答经过 M 次操作之后, 数组从左到右每个数是多少?
输入格式
第一行包含 2 个整数, N 和 M 。
以下 M 行每行一个操作, 其中 L表示左移 x, R 表示右移 x 。
输出格式
输出 N 个数, 代表操作后的数组。
样例输入
5 3
L 3
L 2
R 1
样例输出
2 3 4 5 1
样例说明
样例中的数组变化如下:
[1,2,3,4,5]→[3,1,2,4,5]→[2,3,1,4,5]→[2,3,4,5,1]
评测用例规模与约定
对于 50% 的评测用例, 1≤N,M≤10000.
对于 100% 的评测用例, 1≤N,M≤200000,1≤x≤N.
运行限制
最大运行时间:3s
最大运行内存: 512M
初始代码:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N, M; N = sc.nextInt(); M = sc.nextInt(); int[] arr = new int[N + 2]; for (int i = 1; i <= N; i++) { arr[i] = i; } Character key; Integer value; for (int i = 0; i < M; i++) { key = sc.next().charAt(0); value = sc.nextInt(); if (key.toString().equals("L")) { Lexchange(arr, value, N); } else { Rexchange(arr, value, N); } } int[] R = new int[N + 1]; for (int i = 1; i <= N; i++) { R[arr[i]] = i; } for (int i = 1; i <= N; i++) { System.out.print(R[i]+" "); } } public static void Lexchange(int[] arr, int x, int N) { int j = 0; for (int i = 1; i <= N; i++) { if (arr[i] < arr[x]) { arr[i]++; j++; } if (j == arr[x] - 1) { arr[x] = 1; return; } } } public static void Rexchange(int[] arr, int x, int N) { int j = 0; for (int i = 1; i <= N; i++) { if (arr[i] > arr[x]) { arr[i]--; j++; } if (j == N-arr[x]) { arr[x]=N; return; } } } }
|
看到题目后想到的方法,也是基本思路吧,首先找一个arr数组存储每一个数的位置,比如arr[1]=1;就是1在1的位置。
arr数组初始arr[i]=i;每一个数都在初始位置。
左移例如L 3 那么就将arr[3]=1,在3之前的1,2的位置全部加1,依次类推。
右移例如R 3 那么就将arr[3]=N,在3之后的4,5,····,N的位置全部减一,依次类推。
最后根据记录的位置将数字输出即可。
但提交后只能通过50%的用例,其它运行超时,于是进行改进。
改进后代码:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N, M; N = sc.nextInt(); M = sc.nextInt(); int[][] arr = new int[N+1][2]; for (int i = 1; i <= N; i++) { arr[i][0]=arr[i][1]=i; } Character key; Integer value; int L=0,R=N+1; for (int i = 0; i < M; i++) { key = sc.next().charAt(0); value = sc.nextInt(); if (key.toString().equals("L")) { Lexchange(arr, value, L); L--; } else { Rexchange(arr, value, R); R++; } } kuaipai(arr,1,N); for (int i=1;i<=N;i++){ System.out.print(arr[i][0]+" "); } } public static void Lexchange(int[][] arr, int x,int L) { arr[x][1]=L; } public static void Rexchange(int[][]arr, int x,int R) { arr[x][1]=R; } public static void kuaipai(int [][] a,int l,int r){ if (l>=r){ return; } int prive=a[l][1]; int e=a[l][0]; int b=l,c=r; while(b<c){ while(a[c][1]>=prive&&b<c){ c--; } while (a[b][1]<=prive&&b<c){ b++; } if (b<c){ int d=a[b][0]; a[b][0]=a[c][0]; a[c][0]=d; int tem=a[b][1]; a[b][1]=a[c][1]; a[c][1]=tem; } } a[l][1]=a[c][1]; a[l][0]=a[c][0]; a[c][1]=prive; a[c][0]=e; kuaipai(a,c+1,r); kuaipai(a,l,c-1); } }
|
看其它解题思路时看到了权值,于是用二维数组存储数字与权值。
初始时 arr[i][0]=arr[i][1]=i;每个数的权值就是它本身。
然后因为要左移右移所以我们设置左右权值L=0,R=N+1。(该数组下标是从1——N保证没有重复)
然后左移比如L 3就将arr[3][1]=L;然后左权值L减一,依次类推。
右移比如R 3就将arr[3][1]=R;然后右权值R加一,依次类推。
操作完毕后将数组按照权值排序并输出即可。