昨天我做完阿里2016实习招聘的笔试题,在三道附加题中有一道题的大致内容是这样的:
说的是用户购物之后的物流情况,由于物流公司的物流信息有时因为某些原因没有按照发件、配送、收件的顺序给公司,客户端在处理这些信息时往往存在物流消息顺序不对、或者多个重复但不同时的物流操作等问题,物流信息主要有两个部分:操作时间和操作内容,现在需要你写一个非递归的归并排序算法来将这些物流信息按客户需要的顺序排好,如果存在多个相同的物流操作则保留第一次操作的时间,将后面有相同操作的信息删去。(大致就是这个意思吧,原话不记得了……),具体的数据源没给,我使用的是map中的key存储物流时间,value存物流操作,按我常看大的物流信息随便编了一组数据,归并算法使用的2路非递归归并。具体代码如下:
package vivien;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
public class testTmp {
public void addItem(Map<int[],String> map){
//客户端拿到的数据源往里添加
map.put(new int[]{2014,2,3,17},"取货");
map.put(new int[]{2014,2,3,20},"取货");
map.put(new int[]{2014,2,3,7},"取货");
map.put(new int[]{2014,2,5,7},"转运到B地");
map.put(new int[]{2014,2,4,17},"转运到A地");
map.put(new int[]{2014,2,6,9},"转运到C地");
map.put(new int[]{2014,2,7,21},"转运到D地");
map.put(new int[]{2014,2,8,7},"快递员派送");
map.put(new int[]{2014,2,8,13},"已签收");
}
public void PrintEntry(Map<int[],String> map){
for(Map.Entry<int[], String> entry:map.entrySet()){
if (entry != null)
System.out.println(entry.getKey()[0]+":"+
entry.getKey()[1]+":"+
entry.getKey()[2]+":"+
entry.getKey()[3]+":"+
entry.getValue());
}
}
public static void main(String[] args){
Map<int[],String> Orimap = new LinkedHashMap<int[],String>();
testTmp obj = new testTmp();
obj.addItem(Orimap);
obj.PrintEntry(Orimap);
Map<int[],String> map_sorted = obj.mergeSort(Orimap);//先对key由小到大排序
obj.PrintEntry(map_sorted);
}
public Map<int[],String> mergeSort(Map<int[],String> map){
//归并排序
int len = map.size();
//将map中的key取出
Set<int[]> time = map.keySet();
int[][] array = new int[len][4];
//为了方便排序,将set集合中的元素存储到一个二维数组中
Iterator it = time.iterator();
int n=0;
while(it.hasNext())
{
array[n] = (int[]) it.next();
n++;
}
if(len < 2) //长度为0或1,默认已经排好序
return null;
int step=1;//初始步长
int startL,startR;
while(step < len){
startL = 0;
startR = step;
while(startR+step <= len)
{
merge(array,startL,startL+step,startR,startR+step);
startL=startR+step;
startR=startL+step;
}
if(startR < len){
merge(array,startL,startL+step,startR,len);
}
step*=2;//2路归并排序
}
Map<int[],String> SortedMap = new LinkedHashMap<int[],String>();
for (n=0;n<array.length;n++)
{
SortedMap.put(array[n],map.get(array[n]));
}
//去除map中物流信息相同的元素
for(int i=0;i<array.length;i++){
for(int j=i+1;j<array.length;j++)
{
if ( SortedMap.get(array[j]) != null && SortedMap.get(array[i]) != null
&& SortedMap.get(array[i]).equals(SortedMap.get(array[j])) )
SortedMap.remove(array[j]);
}
}
return SortedMap;
}
public void merge(int[][] a,int startL,int stopL,int startR,int stopR){
int[][] right = new int[stopR - startR + 1][4];
int[][] left = new int[stopL - startL + 1][4];
for(int i=0,k=startR;i<(right.length-1);++i,++k) //二维数组的length指数组的行数 二维数组[行下标].length才是二维数组的列数
{
right[i] = a[k];
}
for(int n=0,k=startL;n<(left.length-1);++n,++k)
{
left[n] = a[k];
}
right[right.length-1] = new int[]{Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE};
left[left.length-1] = new int[]{Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE};
for(int k=startL,n=0,m=0;k<stopR;k++)
{
if(MyCompare(left[m],right[n]) <= 0)
{
a[k]=left[m];
m++;
}else{
a[k]=right[n];
n++;
}
}
}
public int MyCompare(int[] left,int[] right){
int result = 0;
int len =left.length;
int dex = 0;
while(dex < len)
{
if (left[dex] == right[dex])
{
dex++;
}else if(left[dex] > right[dex])
{
result = 1;
break;
}else
{
result = -1;
break;
}
}
if (dex==len)
{
return result;
}
return result;
}
}
程序运行结果:
2014:2:3:17:取货
2014:2:3:20:取货
2014:2:3:7:取货
2014:2:5:7:转运到B地
2014:2:4:17:转运到A地
2014:2:6:9:转运到C地
2014:2:7:21:转运到D地
2014:2:8:7:快递员派送
2014:2:8:13:已签收
2014:2:3:7:取货
2014:2:4:17:转运到A地
2014:2:5:7:转运到B地
2014:2:6:9:转运到C地
2014:2:7:21:转运到D地
2014:2:8:7:快递员派送
2014:2:8:13:已签收
2014:2:3:20:取货
2014:2:3:7:取货
2014:2:5:7:转运到B地
2014:2:4:17:转运到A地
2014:2:6:9:转运到C地
2014:2:7:21:转运到D地
2014:2:8:7:快递员派送
2014:2:8:13:已签收
2014:2:3:7:取货
2014:2:4:17:转运到A地
2014:2:5:7:转运到B地
2014:2:6:9:转运到C地
2014:2:7:21:转运到D地
2014:2:8:7:快递员派送
2014:2:8:13:已签收
但是这个代码存在一些问题,我这里并没有使用comparator和comparable,导致我中间需要自己new一个map存储排好序的二维数组,内存占用变大。而且这个排好序的map中有null值,以后如果要再用它会出现一些问题,以上的代码只是一个雏形,后续会再修改。
代码中不完美的地方还恳请广大网友批评指正~蟹蟹~