两个有序链表序列的合并
分数 20
已知两个非降序链表序列S1与S2,设计函数构造出S1与S2合并后的新的非降序链表S3。
输入格式:
输入分两行,分别在每行给出由若干个正整数构成的非降序序列,用−1表示序列的结尾(−1不属于这个序列)。数字用空格间隔。
输出格式:
在一行中输出合并后新的非降序链表,数字间用空格分开,结尾不能有多余空格;若新链表为空,输出NULL
。
输入样例:
1 3 5 -1
2 4 6 8 10 -1
输出样例:
1 2 3 4 5 6 8 10
这个题一眼看上去不难,就是双指针的应用,两个指针分别指向两个数组,然后比较大小后放进新的数组,代码如下:
import java.util.Scanner;
public class L1010_ {
public static void main(String[] args) {
Scanner sc =new Scanner(System.in);//创建Scanner类
String[] str1=sc.nextLine().split(" ");//String类的split分割方法,可以根据传入的字符串参数将字符串分割成数组
String[] str2=sc.nextLine().split(" ");//将两个链表分割成两个字符串数组
int[] arr1=new int[str1.length];//创建整数数组,用于储存数字方便后续处理
int[] arr2=new int[str2.length];
for(int i=0;i<arr1.length;i++){
arr1[i]= Integer.parseInt(str1[i]);//调用Integer类的parseInt方法将String转换成int
}
for(int i=0;i<arr2.length;i++){
arr2[i]=Integer.parseInt(str2[i]);//将两个字符串数组转换成整数数组,方便比较
}
int[]arr=new int[arr1.length+ arr2.length-2];//创建合并后的数组,因为原始数组都是以-1结尾,所以要将结尾的-1忽略掉,所以-2
int id=0;//合并后的数组指针
int left1=0;//arr1的指针
int left2=0;//arr2的指针
//因为这两个链表是非降序的,所以就是升序排序的数组,所以从左往右依次比较,
//数字小的就放入合并后的数组,然后将指针后移,进行下次比较
//直到有一个数组所有数字都放进了,合并数组里,此时结束循环
//然后判断哪个数组没有放进去,再将未放进去的数字都依次放进去
while(left1<arr1.length-1&&left2<arr2.length-1){
if(arr1[left1]<arr2[left2]){//每次通过从arr1 arr2的下标访问元素,然后比较
arr[id++]=arr1[left1++];//小的就放进合并数组arr里,并将下标++,也就是后移
}else{
arr[id++]=arr2[left2++];
}
}
if(left1==arr1.length-1){//判断哪个数组没有全部访问玩,
for(int i=left2;i<arr2.length-1;i++){
arr[id++]=arr2[i];//将剩下的数字依次放入合并数组中
}
}else{
for(int i=left1;i<arr1.length-1;i++){
arr[id++]=arr1[i];
}
}
if(arr.length==0){//再根据合并数组大小判断答案,若数组大小为0则两个数组都为空,此时输出NULL
System.out.print("NULL");
}else{
System.out.print(arr[0]+"");//不为空时就依次输出合并数组的元素
for(int i=1;i<arr.length-1;i++){
System.out.print(" "+arr[i]);
}
}
}
}
但是java提交上去,最后一个测试点一直超时(或者内存超限),这个题的难点就在这里,因为java的输入(Scanner)输出(System.out.println())相比c语言来说,要慢的多。
在数据量小得情况下还好,一旦数据量大起来就特别容易超时,此题用Scanner输入就会超时,所以就需要更快得输入 BufferedReader:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws java.io.IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 创建BufferedReader类
String line = br.readLine(); // 输入的一行字符
System.out.println(line);
}
}
用BufferedReader类进行读取时,会有一个异常:IOException,用try代码太多,就在主类后面throw抛出就好了:throws java.io.IOException
这时我们将输入的Scanner类改成BufferedReader类
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws java.io.IOException{
BufferedReader br =new BufferedReader(new InputStreamReader(System.in));
String[] str1=br.readLine().split(" ");//读入一行数组再进行处理
String[] str2=br.readLine().split(" ");
}
}
此时提交还是会显示超时,所以还需要优化代码,现在还有一个优化的一个点就是输出,java的输出也是很慢的,所以就有了快速输出:BufferedWriter类
创建格式跟BufferedReader类 类似
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
bw.write("NULL");//输入缓冲区
bw.flush();//输出控制台,write后面必须跟这个,否则就会打印不出来
将输出用的System.out.print(),全部换成BufferedWriter,
此时代码就为:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class Main {
public static void main(String[] args) throws java.io.IOException{
BufferedReader br =new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
String[] str1=br.readLine().split(" ");
String[] str2=br.readLine().split(" ");
int[] arr1=new int[str1.length];
int[] arr2=new int[str2.length];
for(int i=0;i<arr1.length;i++){
arr1[i]= Integer.parseInt(str1[i]);
}
for(int i=0;i<arr2.length;i++){
arr2[i]=Integer.parseInt(str2[i]);
}
int[]arr=new int[arr1.length+ arr2.length-2];
int id=0;
int left1=0;
int left2=0;
while(left1<arr1.length-1&&left2<arr2.length-1){
if(arr1[left1]<arr2[left2]){
arr[id++]=arr1[left1++];
}else{
arr[id++]=arr2[left2++];
}
}
if(left1==arr1.length-1){
for(int i=left2;i<arr2.length-1;i++){
arr[id++]=arr2[i];
}
}else{
for(int i=left1;i<arr1.length-1;i++){
arr[id++]=arr1[i];
}
}
if(arr.length==0){
bw.write("NULL");
bw.flush();
}else{
bw.write(arr[0]+"");//这里要注意,直接输出数字可能输出乱码,要加上一个空字符,将它变成字符串类型再输出就不会变成乱码了
for(int i=1;i<arr.length;i++){
bw.write(" "+arr[i]);
}
bw.flush();
}
}
}
String类split() 方法:
https://www.runoob.com/java/java-string-split.html