今天练习算法时,看到了一道经典的排序题,分享一下:
题目描述:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
图书馆最近新进了一批书,管理员们需要把这些书按照所属类别以及书名分别放置在不同的书架上。但由于书太多了,这可忙坏了管理员们,你能帮他们整理一下这些新书吗?
输入描述:
输入包含多组数据。 每组数据第一行包含一个正整数n (1≤n≤1000)。
紧接着n行,每行包含一个书名和这本书的所属类别。书名和类别名都只有字母构成,并且长度均不超过32个字 符。
输出描述:
对应每一组数据,按照要求先按照类别排序(大小写无关),再按照书名排序(大小写无关),最后输出排好序的书名,每一个书名占一行。
每一组数据之后输出一个空行做分隔符。
测试用例(输入):
3
JavaScriptInAction Programming
OnLisp Lisp
LetOverLambda Lisp
3
abc ZZZ
XXX AAA
DEF AAA
输出:
LetOverLambda
OnLisp
JavaScriptInAction
DEF
XXX
abc
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
下面我们分析一下这道题,这道题一看都知道是一个排序题,题目中先让按类别排序,在按书名排序,思想很简单,但是具体怎么实现呢?而且这样的排序,在我们平时经常会使用。下面我们详细介绍怎样用Java实现这个排序。
Java中有个Comparator接口,一般我们对集合对象或者数组对象排序都需要实现这个接口,并重写(注意和重载的区别)Compare方法,来实现自己定义的排序。
下面我们实现一下这个接口:
<span style="font-size:18px;">public class StepComparator implements Comparator<Step>{ @Override public int compare(Book o1, Book o2) { if(o1.category.toLowerCase().equals(o2.category.toLowerCase())){ return o1.name.toLowerCase().compareTo(o2.name.toLowerCase()); } return o1.category.toLowerCase().compareTo(o2.category.toLowerCase()); } } </span>
这样我们就完全实现了上述排序的功能,然后将输入的数据保存成对象集合,调用这个方法即可。
下面贴上完整的代码
<span style="font-size:18px;">import java.util.*; /** * Created by 华夏紫云 on 2015/11/28. */ public class Main { public static void main(String[] args) { Scanner sc=new Scanner(System.in); while (sc.hasNext()) { int n=sc.nextInt(); ArrayList<Book> input=new ArrayList<Book>(); for(int i=0;i<n;i++){ Book bk=new Book(); bk.name=sc.next(); bk.category=sc.next(); input.add(bk); } Comparator<Book> mycom=new Comparator<Book>() { public int compare(Book o1, Book o2) { if(o1.category.toLowerCase().equals(o2.category.toLowerCase())){ return o1.name.toLowerCase().compareTo(o2.name.toLowerCase()); } return o1.category.toLowerCase().compareTo(o2.category.toLowerCase()); } }; Collections.sort(input,mycom); for(int i=0;i<input.size();i++){ System.out.println(input.get(i).name); } System.out.println(); } } } class Book{ String name; String category; } </span>
和这个题很类似的还有这样一个题,是搜狐的一道在线编程题,下面先给出题目描述:
搜狐员工小王最近利用假期在外地旅游,在某个小镇碰到一个马戏团表演,精彩的表演结束后发现团长正和大伙在帐篷前激烈讨论,小王打听了下了解到, 马戏团正打算出一个新节目“最高罗汉塔”,即马戏团员叠罗汉表演。考虑到安全因素,要求叠罗汉过程中,站在某个人肩上的人应该既比自己矮又比自己瘦,或相等。 团长想要本次节目中的罗汉塔叠的最高,由于人数众多,正在头疼如何安排人员的问题。小王觉得这个问题很简单,于是统计了参与最高罗汉塔表演的所有团员的身高体重,并且很快找到叠最高罗汉塔的人员序列。 现在你手上也拿到了这样一份身高体重表,请找出可以叠出的最高罗汉塔的高度,这份表中马戏团员依次编号为1到N。
上面这道题其实也很简单,我们之前肯定做过求最长递增序列的题。在求最长递增序列的题时,有两种办法。
1、动态规划,按顺序打表,最后求出最长递增的序列。时间复杂度为O(n^2);
2、二分查找法,每次替换队列或栈中的一个数,最后输出该队列或栈的长度。时间复杂度为(n*LogN);
显然第二种方法好。下面我给出我自己的求最长递增序列的二分查找法的代码:
<span style="font-size:18px;">import java.util.*; public class Stack { public int getHeight(int[] men, int n) { ArrayList<Integer> arry=new ArrayList<Integer>(); for(int i=0;i<n;i++){ if(arry.isEmpty()){ arry.add(men[i]); }else{ if(men[i]>arry.get(arry.size()-1)){ arry.add(men[i]); }else{ arry.set(Biner(men[i], arry), men[i]); } } } return arry.size(); } int Biner(int k,ArrayList<Integer> arry){ int low=0; int high=arry.size()-1; while(low<=high){ int mid=(low+high)/2; if(arry.get(mid)>k){ high=mid-1; }else if(arry.get(mid)<k){ low=mid+1; }else { return mid; } } return low; } } </span>
下来我们分析这个题,这个题呢,其实思路也是有点和递增序列像,只不过这个题是二维的,我们可以这样做,先将身高,按从低到高排序,然后,我们只需要找出体重的最长递增序列即可(要注意当身高相等时候,体重是按照从大到小排的),这样,这道题就转换为求最长递增序列的题,只不过增加了和第一道题一样的对象排序。下面分享自己的代码:
<span style="font-size:18px;"> import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc=new Scanner(System.in); while (sc.hasNext()) { int n=sc.nextInt(); ArrayList<Person> Arry=new ArrayList<Person>(); for(int i=0;i<n;i++){ Person p=new Person(); p.index=sc.nextInt(); p.weight=sc.nextInt(); p.height=sc.nextInt(); Arry.add(p); } Comparator<Person> comparex=new Comparator<Person>() { public int compare(Person o1, Person o2) { if(o1.weight!=o2.weight){ return (o1.weight-o2.weight); } return (o2.height-o1.height); } }; Collections.sort(Arry, comparex); ArrayList<Integer> rs=new ArrayList<Integer>(); for(int i=0;i<n;i++){ if(rs.isEmpty()){ rs.add(Arry.get(i).height); }else{ if(rs.get(rs.size()-1)<=Arry.get(i).height){ rs.add(Arry.get(i).height); }else{ rs.set(Bin(rs, Arry.get(i).height), Arry.get(i).height); } } } System.out.println(rs.size()); } } private static int Bin(ArrayList<Integer> arry,int k) { int low =0; int high=arry.size()-1; while(low<=high){ int mid=(low+high)/2; if(arry.get(mid)>k){ high=mid-1; }else if(arry.get(mid)<k){ low=mid+1; }else { return mid+1; } } return low; } } class Person{ int index; int weight; int height; } </span>
如果有什么问题,欢迎评论。