洛谷题单:【算法1-2】排序

(1)P1271 【深基9.例1】选举学生会
这题对于C++的选手来说不算题目,直接调快速排序即可。但这可苦了java选手,java直接用快排会超时,所以得使用一个更高效的算法,桶排序,把数据装进1000的大小的数组里,数据元素值对应着数组下标,个数对应着数组的值,这样Java就可以过了。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

public class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		PrintWriter out =new PrintWriter(System.out);
		String[] s=br.readLine().split(" ");
		int n=Integer.valueOf(s[0]),m=Integer.valueOf(s[1]);
		int[] arr=new int[n+1];
		s=br.readLine().split(" ");
		for(int i=0;i<m;i++) {
			arr[Integer.valueOf(s[i])]++;
		}
		for(int i=1;i<=n;i++) {
			for(int j=arr[i];j>0;j--)
				out.print(i+" ");
		}
		out.close();
	}
}

(2)P1177 【模板】快速排序
本来是一个练练快速排序的模板,可是java的递归只能一万层,手写了一个对于大数据会RE,只好使用java自带的快速排序了。但这里我还是给出了手写快排的代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
	static int[] arr;
	public static void main(String[] args) throws  IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		int n=Integer.valueOf(br.readLine());
		String[] s=br.readLine().split(" ");
		arr=new int[n];
		for(int i=0;i<n;i++) {
			arr[i]=Integer.valueOf(s[i]);
		}
		sort(0,n-1);
		for(int i=0;i<n;i++) {
			System.out.print(arr[i]+" ");
		}
	}
	public static void sort(int l,int r) {
		if(l<r) {
			int p=partition(l,r);
			sort(l,p-1);
			sort(p+1,r);
		}
	}
	public static int partition(int l,int r) {
		int m=arr[l],i=l,j=r;
		while(i<j) {
			while(arr[j]>=m&&i<j)j--;
			while(arr[i]<=m&&i<j)i++;
			if(i<j)swap(i,j);
		}
		swap(l,j);
		return j;
	}
	public static void swap(int i,int j) {
		int temp=arr[i];
		arr[i]=arr[j];
		arr[j]=temp;
	}
}

(3)P1923 【深基9.例4】求第 k 小的数
这道题很巧妙,要用到快速排序的思想。如果直接全部数据快排肯定不行的。快速排序一趟的时候,我们在中间找到了一个值arr[q],这个值是第q-left小的数字,然后把它与k进行比较,如果相等,直接输出并结束递归,如果大于k,则说明在左边递归,小于则说明在右边递归

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
	static int[] arr;
	public static void main(String[] args) throws IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		String[] s=br.readLine().split(" ");
		int n=Integer.valueOf(s[0]),m=Integer.valueOf(s[1]);
		arr=new int[n];
		s=br.readLine().split(" ");
		for(int i=0;i<n;i++) {
			arr[i]=Integer.valueOf(s[i]);
		}
		System.out.println(sort(0,n-1,m));
	}
	public static int sort(int l,int r,int k) {
		int q=partition(l, r);
		int qk=q-l;
		if(qk==k) {
			return arr[q];
		}
		else if(qk>k) {
			return sort(l,q-1,k);
		}
		else {
			return sort(q+1,r,k-qk-1);
		}
	}
	public static int partition(int l,int r) {
		int m=arr[l],i=l,j=r;
		while(i<j) {
			while(arr[j]>=m&&i<j)j--;
			while(arr[i]<=m&&i<j)i++;
			if(i<j)swap(i,j);
		}
		swap(l,j);
		return j;
	}

	public static void swap(int i,int j) {
		int temp=arr[i];
		arr[i]=arr[j];
		arr[j]=temp;
	}
}

(4)P1059 明明的随机数
用C++不知道有没有这么方便,反正用java的TreeSet直接自带去重排序功能。


import java.util.Scanner;
import java.util.TreeSet;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		TreeSet<Integer> ts=new TreeSet<Integer>();
		for(int i=0;i<n;i++) {
			ts.add(sc.nextInt());
		}
		System.out.println(ts.size());
		for(int i:ts) {
			System.out.print(i+" ");
		}
	}
}

(5)P1093 奖学金
经过了结构体那个题单的学习,这对一个类进行排序是一个很简单的题目,按照要求排序即可。

import java.util.Arrays;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		peo[] p=new peo[n];
		for(int i=0;i<n;i++) {
			int a=sc.nextInt(),b=sc.nextInt(),c=sc.nextInt();
			p[i]=new peo(i+1,a,a+b+c);
		}
		Arrays.sort(p);
		for(int i=0;i<5;i++) {
			System.out.println(p[i].id+" "+p[i].b);
		}
	}
}
class peo implements Comparable<peo>{
	int id,a,b;
	peo(int idd,int aa,int bb){
		id=idd;a=aa;b=bb;
	}
	@Override
	public int compareTo(peo o) {
		if(a==o.a&&b==o.b)return id-o.id;
		if(b==o.b)return o.a-a;
		return o.b-b;
	}
	
}

(6)P1781 宇宙总统
除了需要一下大数运算没有别的操作了,维护一个最大值,并把它的索引保留。


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;

public class Main {
	public static void main(String[] args) throws IOException{
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		int n=Integer.valueOf(br.readLine());
		int index=1;
		BigInteger bi=new BigInteger(br.readLine());
		BigInteger bi2=new BigInteger("0");
		for(int i=2;i<=n;i++) {
			bi2=new BigInteger(br.readLine());
			if(bi2.compareTo(bi)==1) {
				bi=bi2;
				index=i;
			}
		}
		System.out.println(index);
		System.out.println(bi);
	}
}

(7)P2676 [USACO07DEC]Bookshelf B
一道简单贪心+排序的题目。肯定身高越高越好拿,所以从大到小排序,然后一直加牛的个数,直到能够到书架。

import java.util.Arrays;
import java.util.Scanner;

public class Main{
	public static void main(String[] args) {
		Scanner sc=new Scanner (System.in);
		int n=sc.nextInt(),m=sc.nextInt();
		int[] arr=new int[n];
		for(int i=0;i<n;i++) {
			arr[i]=sc.nextInt();
		}
		Arrays.sort(arr);
		int sum=0,num=0;;
		for(int i=n-1;i>=0;i--) {
			sum+=arr[i];
			num++;
			if(sum>=m) {
				break;
			}
		}
		System.out.println(num);
	}
}

(8)P1116 车厢重组
令人怀念的冒泡排序法,每趟把最大的数冒泡到最后一个,进行n躺排序,每次交换计数,输出最后的交换次数

import java.util.Scanner;

public class Main{
	static int[] arr;
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		arr=new int[n];
		for(int i=0;i<n;i++) {
			arr[i]=sc.nextInt();
		}
		int sum=0;
		for(int i=0;i<n;i++) {
			for(int j=0;j<n-i-1;j++) {
				if(arr[j]>arr[j+1]) {
					swap(j,j+1);
					sum++;
				}
			}
		}
		System.out.println(sum);
	}
	public static void swap(int i,int j) {
		int temp=arr[i];
		arr[i]=arr[j];
		arr[j]=temp;
	}
}

(9)P1152 欢乐的跳
两种方法,一种是开一个大的布尔类型数组,然后记录每两个元素的差值的绝对值。然后遍历这个数组,如果1-n-1中有元素没有标记过,说明不符合题意,反之符合。第二种方法,用一个数组存下所有差值,然后进行排序,最后与1-n-1对比,如果有不同就不符合。我这里用的是第二种,因为第一种要开的数组很大。

import java.util.Arrays;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int[] arr=new int[n];
		int a=sc.nextInt();
		for(int i=1;i<=n-1;i++) {
			int b=sc.nextInt();
			arr[i]=Math.abs(a-b);
			a=b;
		}
		Arrays.sort(arr);
		for(int i=1;i<=n-1;i++) {
			if(arr[i]!=i) {
				System.out.println("Not jolly");
				return;
			}
		}
		System.out.println("Jolly");
	}
}

(10)P1068 分数线划定
这题和其他普通的结构体排序相比有一点坑,就是先要选定一个分数线,但在这个分数线的人数可能不止一人,你要保证他们全部进入面试,所以可能真正面试的人数可能会多余化分数线应该对于的人数。


import java.util.Arrays;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int m=sc.nextInt();
		p[] arr=new p[n];
		for(int i=0;i<n;i++) {
			arr[i]=new p(sc.nextInt(),sc.nextInt());
		}
		Arrays.sort(arr);
		int a=(int) Math.floor(m*1.5);
		while(arr[a-1].score==arr[a].score&&a>1&&a<arr.length) {
			a++;
		}
		System.out.print(arr[a-1].score+" "+a);
		System.out.println();
		for(int i=0;i<=a-1;i++) {
			System.out.println(arr[i].id+" "+arr[i].score);
		}
		
	}
}
class p implements Comparable<p>{
	int id;
	int score;
	p(int id,int score){
		this.id=id;
		this.score=score;
	}
	@Override
	public int compareTo(p o) {
		if(o.score==score)
			return id-o.id;
		return o.score-score;
	}
}

(11)P5143 攀爬者
把坐标按照z进行从小到大排序,然后从第二项开始,算出减去前面一个点的距离,然后累加。最后输出。

import java.util.Arrays;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		point[] p=new point[n];
		for(int i=0;i<n;i++) {
			p[i]=new point(sc.nextInt(), sc.nextInt(), sc.nextInt());
		}
		Arrays.sort(p);
		double sum=0;
		for(int i=1;i<n;i++) {
			sum+=Math.sqrt((p[i].x-p[i-1].x)*(p[i].x-p[i-1].x)+(p[i].y-p[i-1].y)*(p[i].y-p[i-1].y)+(p[i].z-p[i-1].z)*(p[i].z-p[i-1].z));
		}
		System.out.println(String.format("%.3f", sum));
	}
}
class point implements Comparable<point>{
	int x,y,z;
	point(int xx,int yy,int zz){
		x=xx;y=yy;z=zz;
	}
	@Override
	public int compareTo(point o) {
		return z-o.z;
	}
}

(12)P1104 生日
我觉得出题人是怎么样做到对生日比大小的,明明是对年龄比大小好嘛。不管那么多,这题就是一个结构体排序而已,年龄大的先输出,年龄相同的编号在后面的先输出。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		int n=Integer.valueOf(br.readLine());
		pp[] p=new pp[n];
		for(int i=0;i<n;i++) {
			String[] s=br.readLine().split(" ");
			p[i]=new pp(s[0],i,Integer.valueOf(s[1]),Integer.valueOf(s[2]),Integer.valueOf(s[3]));
		}
		Arrays.sort(p);
		for(int i=0;i<n;i++) {
			System.out.println(p[i].name);
		}
	}
}

class pp implements Comparable<pp>{
	String name;
	int id,a,b,c;
	pp(String n,int idd,int aa,int bb,int cc){
		name=n;id=idd;a=aa;b=bb;c=cc;
	}
	@Override
	public int compareTo(pp o) {
		if(a==o.a&&b==o.b&&c==o.c)return o.id-id;
		if(a==o.a&&b==o.b)return c-o.c;
		if(a==o.a)return b-o.b;
		return a-o.a;
	}
	
}

(13)P1012 拼数
完全是考察自定义排序的一题啦,怎么排列能排出最大的数?首先,两个数进行比较谁放前面肯定不是单纯的比大小,而是比首位数字的大小,大的放前面。如果首位相同则比第二位,如果全部相同的话,就要根据长度长的那个数字的第一位和最后一位来确定是否这个数放前面,例如13 和137比较,因为对应位数都相同,所以就看137的第一位和最后一位,如果最后一位大,则这个数字放前面,形成13713.而如果是73和731比较,那么则是73放前面形成73731.


import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		sc.nextLine();
		String[] s=sc.nextLine().split(" ");
		MyComparator cmp=new MyComparator();
		Arrays.sort(s,cmp);
		StringBuilder sb=new StringBuilder();
		for(int i=0;i<s.length;i++) {
			sb.append(s[i]);
		}
		System.out.println(sb);
	}
}
class MyComparator implements Comparator<String>{

	@Override
	public int compare(String o1, String o2) {
		for(int i=0;i<Math.min(o1.length(), o2.length());i++) {
			if(o1.charAt(i)!=o2.charAt(i)) {
				return o2.compareTo(o1);
			}
		}
		if(o1.length()>o2.length()) {
			return o1.charAt(0)-o1.charAt(o1.length()-1);
		}
		else {
			return o2.charAt(o2.length()-1)-o2.charAt(0);
		}
	}
	
}

你可能感兴趣的:(洛谷题单java解析)