前言

今天下午做了拼多多在牛客网上的在线笔试题,感觉自己的智商被鄙视到了···不过其中一道题的某一部分引起了我极大的兴趣,感觉可以总结一下,做好积累~

题目的部分我拍照如下所示


这里面最复杂的就是第3点,对秒杀活动进行排序,排序条件多,排序条件使用各不相同,在笔试中给我带来了很大的困扰,最后当然也是没做完啦····
解决方案 吃完晚饭开始寻找解决方法,觉得应该会很有意思,果然看到了比较好的做法,链接在这
java多条件优先级排序 — Comparator 这个方案以我这样几个月的菜鸟看来,最巧妙的就是把 多个比较器 Comparator放进一个 比较器列表 中,然后在需要时,在new一个比较器,然后在其中foreach使用各个比较器,而且注意看他代码24行的if,没有在循环中间返回结果为0的情况,而是在使用完所有比较器最后再返回0;这样就能按顺序依次使用各个比价器了。 那么回到我的题目中来
我先定义了4个比较器,分别用于4中不同项目的排序比较 //按人气从大到小对活动进行排序
private Comparator<Activity> renqiComparator = new Comparator<Activity>() {
@Override
public int compare(Activity o1, Activity o2) {
if(goods.get(o1.goodsId).renQi == goods.get(o2.goodsId).renQi) {
return 0;
} else {
return goods.get(o1.goodsId).renQi > goods.get(o2.goodsId).renQi ? -1 : 1;
}
}
}; //按商品id从小到大排序
private Comparator<Activity> idComparator = new Comparator<Activity>() {
@Override
public int compare(Activity o1, Activity o2) {
if(o1.goodsId == o2.goodsId) {
return 0;
} else {
return o1.goodsId > o2.goodsId ? 1 : -1;
}
}
}; //按活动开始时间从早到晚排序
private Comparator<Activity> startTimeComparator = new Comparator<Activity>() { @Override
public int compare(Activity o1, Activity o2) {
if(o1.startTime == o2.startTime) {
return 0;
} else {
return o1.startTime > o2.startTime ? 1 :-1;
}
}
}; //按活动的最后卖出时间从晚到早排序
private Comparator<Activity> sellTimeComparator = new Comparator<Activity>() { @Override
public int compare(Activity o1, Activity o2) {
if(o1.sellTime == o2.sellTime) {
return 0;
} else {
return o1.sellTime > o2.sellTime ? -1 : 1;
}
}
}; 然后定义了三个比较器列表,分别用于三种情况下的比较,然后在构造器中初始化这3个比较器列表 public Main3() {
//在构造器中把这个复杂的比较器列表进行初始化
//对于进行中(未售罄)的活动,按商品人气从高到低、商品ID从小到大排序
activityComparatorList1.add(renqiComparator);
activityComparatorList1.add(idComparator); //对于进行中(已售罄)的活动,按最后卖出时间从晚到早、商品人气从高到低、商品ID从小到大排序
activityComparatorList2.add(sellTimeComparator);
activityComparatorList2.add(renqiComparator);
activityComparatorList2.add(idComparator); //对于未开始的活动,依次按开始时间从早到晚、商品人气从高到低、商品ID从小到大排序
activityComparatorList3.add(startTimeComparator);
activityComparatorList3.add(renqiComparator);
activityComparatorList3.add(idComparator);
} 最后再需要对活动排序的地方这样使用,针对不同阶段使用不同的比较器列表。 Collections.sort(list, new Comparator<Activity>() { @Override
public int compare(Activity o1, Activity o2) { //在同一阶段内的比较
if(o1.limitQuantity>0 && o2.limitQuantity>0) {//进行中未售罄
for(Comparator<Activity> comparator : activityComparatorList1) {
if(comparator.compare(o1, o2) < 0) {
return -1;
} else if(comparator.compare(o1, o2) > 0) {
return 1;
}
}
return 0; //关键在这,里面的比较器给出0时不处理,指导全部比较完成都相等的情况下才给出0 } else if(o1.limitQuantity == 0 && o2.limitQuantity == 0) {//进行中已售罄
for(Comparator<Activity> comparator : activityComparatorList2) {
if(comparator.compare(o1, o2) < 0) {
return -1;
} else if(comparator.compare(o1, o2) > 0) {
return 1;
}
}
return 0; //关键在这,里面的比较器给出0时不处理,指导全部比较完成都相等的情况下才给出0 } else if(o1.startTime>time && o2.startTime>time) { //未开始活动
for(Comparator<Activity> comparator : activityComparatorList3) {
if(comparator.compare(o1, o2) < 0) {
return -1;
} else if(comparator.compare(o1, o2) > 0) {
return 1;
}
}
return 0; //关键在这,里面的比较器给出0时不处理,指导全部比较完成都相等的情况下才给出0
} //在不同阶段的比较
if(o1.limitQuantity > 0 && (o2.limitQuantity == 0 || o2.startTime>time)) {
return -1;
} else if(o1.limitQuantity == 0 && o2.startTime>time) {
return -1;
} else {
return 1;
} }
}); 这样我感觉是比较合理的解决了这样一个多重不同条件的比较问题,而且感觉没有使用过多的判断使得逻辑混乱。
附全部代码 这道题最后也没有放在OJ上测试过,所以可能有错,仅供参考 package com.pinduoduo; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Scanner; public class Main3 { public HashMap<Integer, Good> goods = new HashMap<>();
public ArrayList<Activity> activities = new ArrayList<>();
public List<Comparator<Activity>> activityComparatorList1 = new ArrayList<>();
public List<Comparator<Activity>> activityComparatorList2 = new ArrayList<>();
public List<Comparator<Activity>> activityComparatorList3 = new ArrayList<>(); //按人气从大到小对活动进行排序
private Comparator<Activity> renqiComparator = new Comparator<Activity>() {
@Override
public int compare(Activity o1, Activity o2) {
if(goods.get(o1.goodsId).renQi == goods.get(o2.goodsId).renQi) {
return 0;
} else {
return goods.get(o1.goodsId).renQi > goods.get(o2.goodsId).renQi ? -1 : 1;
}
}
}; //按商品id从小到大排序
private Comparator<Activity> idComparator = new Comparator<Activity>() {
@Override
public int compare(Activity o1, Activity o2) {
if(o1.goodsId == o2.goodsId) {
return 0;
} else {
return o1.goodsId > o2.goodsId ? 1 : -1;
}
}
}; //按活动开始时间从早到晚排序
private Comparator<Activity> startTimeComparator = new Comparator<Activity>() { @Override
public int compare(Activity o1, Activity o2) {
if(o1.startTime == o2.startTime) {
return 0;
} else {
return o1.startTime > o2.startTime ? 1 :-1;
}
}
}; //按活动的最后卖出时间从晚到早排序
private Comparator<Activity> sellTimeComparator = new Comparator<Activity>() { @Override
public int compare(Activity o1, Activity o2) {
if(o1.sellTime == o2.sellTime) {
return 0;
} else {
return o1.sellTime > o2.sellTime ? -1 : 1;
}
}
}; public Main3() {
//在构造器中把这个复杂的比较器列表进行初始化
//对于进行中(未售罄)的活动,按商品人气从高到低、商品ID从小到大排序
activityComparatorList1.add(renqiComparator);
activityComparatorList1.add(idComparator); //对于进行中(已售罄)的活动,按最后卖出时间从晚到早、商品人气从高到低、商品ID从小到大排序
activityComparatorList2.add(sellTimeComparator);
activityComparatorList2.add(renqiComparator);
activityComparatorList2.add(idComparator); //对于未开始的活动,依次按开始时间从早到晚、商品人气从高到低、商品ID从小到大排序
activityComparatorList3.add(startTimeComparator);
activityComparatorList3.add(renqiComparator);
activityComparatorList3.add(idComparator);
} public int addActivity(int startTime, int endTime, int goodsId, int limitQuantity) {
if(limitQuantity <= goods.get(goodsId).kuCun) {
Activity activity = new Activity();
activity.startTime = startTime;
activity.endTime = endTime;
activity.goodsId = goodsId;
activity.limitQuantity = limitQuantity;
activity.id = activities.size();
activities.add(activity);
return activity.id;
}
return -1;
} public int buyGoods(int time, int activityId, int quantity) {
Activity activity = activities.get(activityId);
int startTime = activity.startTime;
int endTime = activity.endTime;
int limitQuantity = activity.limitQuantity;
if(time < startTime || time >= endTime) {
return -1;
} else if(quantity > limitQuantity) {
return -1;
} else {
activity.limitQuantity -= quantity;
activity.sellTime = time;
return 0;
} } public List<Activity> getActivityList(int time) {
ArrayList<Activity> list = new ArrayList<>();
for (Activity activity : activities) {
if(time >= activity.startTime && time < activity.endTime) {
list.add(activity);
}
}
Collections.sort(list, new Comparator<Activity>() { @Override
public int compare(Activity o1, Activity o2) { //在同一阶段内的比较
if(o1.limitQuantity>0 && o2.limitQuantity>0) {//进行中未售罄
for(Comparator<Activity> comparator : activityComparatorList1) {
if(comparator.compare(o1, o2) < 0) {
return -1;
} else if(comparator.compare(o1, o2) > 0) {
return 1;
}
}
return 0; //关键在这,里面的比较器给出0时不处理,指导全部比较完成都相等的情况下才给出0 } else if(o1.limitQuantity == 0 && o2.limitQuantity == 0) {//进行中已售罄
for(Comparator<Activity> comparator : activityComparatorList2) {
if(comparator.compare(o1, o2) < 0) {
return -1;
} else if(comparator.compare(o1, o2) > 0) {
return 1;
}
}
return 0; //关键在这,里面的比较器给出0时不处理,指导全部比较完成都相等的情况下才给出0 } else if(o1.startTime>time && o2.startTime>time) { //未开始活动
for(Comparator<Activity> comparator : activityComparatorList3) {
if(comparator.compare(o1, o2) < 0) {
return -1;
} else if(comparator.compare(o1, o2) > 0) {
return 1;
}
}
return 0; //关键在这,里面的比较器给出0时不处理,指导全部比较完成都相等的情况下才给出0
} //在不同阶段的比较
if(o1.limitQuantity > 0 && (o2.limitQuantity == 0 || o2.startTime>time)) {
return -1;
} else if(o1.limitQuantity == 0 && o2.startTime>time) {
return -1;
} else {
return 1;
} }
});
return list;
} public static void main(String[] args) { Scanner sc = new Scanner(System.in);
Main3 main = new Main3();
int n = sc.nextInt();
int m = sc.nextInt();
for(int i=0; i<n; i++) {
Good good = new Good();
good.id = sc.nextInt();
good.renQi = sc.nextInt();
good.kuCun = sc.nextInt();
main.goods.put(good.id, good);
} sc.nextLine();
String[] ask = new String[m];
for(int i=0; i<m; i++) {
ask[i] = sc.nextLine();
}
for(int i=0; i<m; i++) {
String[] command = ask[i].split(" ");
if("add".equals(command[1])) {
int time = Integer.parseInt(command[0]);
int startTime = Integer.parseInt(command[2]);
int endTime = Integer.parseInt(command[3]);
int goodsId = Integer.parseInt(command[4]);
int limitQuantity = Integer.parseInt(command[5]);
System.out.println(main.addActivity(startTime, endTime, goodsId, limitQuantity)); } else if("buy".equals(command[1])) {
int time = Integer.parseInt(command[0]);
int activityId = Integer.parseInt(command[2]);
int quantity = Integer.parseInt(command[3]);
System.out.println(main.buyGoods(time, activityId, quantity)); } else if("list".equals(command[1])){
int time = Integer.parseInt(command[0]);
List<Activity> list = main.getActivityList(time);
for (Activity activity : list) {
System.out.print(activity.id+" ");
}
System.out.println();
}
}
} } class Good {
public int id;
public int renQi;
public int kuCun;
} class Activity {
public int id;
public int startTime;
public int endTime;
public int goodsId;
public int limitQuantity;
public int sellTime;
}

Java 多条件复杂排序小结的更多相关文章

  1. Java内存访问重排序笔记

    >>关于重排序 重排序通常是编译器或运行时环境为了优化程序性能而采取的对指令进行重新排序执行的一种手段. 重排序分为两类:编译期重排序和运行期重排序,分别对应编译时和运行时环境. > ...

  2. Java使用条件语句和循环结构确定控制流

    与任何程序设计语言一样,Java使用条件语句和循环结构确定控制流.本文将简单讲解条件.循环和switch. 一.块作用域 块(block),即复合语句.是指由一对大括号括起来的若干条简单的Java语句 ...

  3. JAVA 变量 数据类型 运算符 知识小结

    ---------------------------------------------------> JAVA 变量 数据类型 运算符 知识小结 <------------------ ...

  4. Java常见异常(Runtime Exception )小结(转)

    原文链接:Java常见异常(Runtime Exception )小结 Java异常体系结构呈树状,其层次结构图如图 1所示:           本文重在Java中异常机制的一些概念.写本文的目的在 ...

  5. Java实现各种内部排序算法

    数据结构中常见的内部排序算法: 插入排序:直接插入排序.折半插入排序.希尔排序 交换排序:冒泡排序.快速排序 选择排序:简单选择排序.堆排序 归并排序.基数排序.计数排序 直接插入排序: 思想:每次将 ...

  6. Java中List的排序和List的MAp

    这里是一个类中类去实现条件优先排序的问题 package com.sun; import java.util.ArrayList; import java.util.Arrays; import ja ...

  7. java keytool证书工具使用小结

    java keytool证书工具使用小结 在Security编程中,有几种典型的密码交换信息文件格式: DER-encoded certificate: .cer, .crt    PEM-encod ...

  8. Java线性表的排序

    Java线性表的排序 ——@梁WP 前言:刚才在弄JDBC的时候,忽然觉得order-by用太多了没新鲜感,我的第六感告诉我java有对线性表排序的封装,然后在eclipse里随便按了一下“.” ,哈 ...

  9. MYSQL根据分类分组取每组一条数据且按条件能排序的写法

    之前在一个项目的开发中,有遇到要根据分类来分组获取每组一条按某个条件字段排序的数据结果,于是先自己写了一条语句: select * from `表A` GROUP BY `c`; 上面这个语句有可以根 ...

随机推荐

  1. jsonp获取股票信息

    源码: <script src="http://hq.sinajs.cn/list=sh600050" charset="gb2312"></ ...

  2. 【题解】Luogu P2787 语文1(chin1)- 理理思维

    原题传送门:P2787 语文1(chin1)- 理理思维 前置芝士:珂朵莉树 窝博客里对珂朵莉树的介绍 没什么好说的自己看看吧 珂朵莉树跑的飞快,但还是没有memset0小姐姐跑得快 操作1:暴力统计 ...

  3. 【面试篇】必须掌握的Spring 常用注解

    注解本身没有功能的,就和 xml 一样.注解和 xml 都是一种元数据,元数据即解释数据的数据,这就是所谓配置. 本文主要罗列 Spring|Spring MVC相关注解的简介. Spring部分 1 ...

  4. 两步完成ssh免密码登录

    1.生成公钥/私钥 ssh-keygen -N '' 生成公钥在/root/.ssh目录下. 2.分发公钥 ssh-copy-id root@192.168.137.141 192.168.137.1 ...

  5. Exp2_固件程序设计 20165226_20165310_20165315

    Exp2_固件程序设计 20165226_20165310_20165315 Exp2_1 MDK 实验内容 注意不经老师允许不准烧写自己修改的代码 两人(个别三人)一组 参考云班课资源中" ...

  6. CSS的再深入(更新中···)

    在上一章我们提到了一个新的概念,叫做块级样式,讲到这里就要科普一下: 标签又分为两种: (1)块级标签 元素特征:会独占一行,无论内容多少,可以设置宽高··· (2)内敛标签(又叫做行内标签) 元素特 ...

  7. 2015,3,10 1(南阳理工ACM)

    描述输入三个字符(可以重复)后,按各字符的ASCII码从小到大的顺序输出这三个字符.   输入 第一行输入一个数N,表示有N组测试数据.后面的N行输入多组数据,每组输入数据都是占一行,有三个字符组成, ...

  8. Yum自动下载RPM包及其所有依赖的包

    前几天我尝试去创建一个仅包含我们经常在 CentOS 7 下使用的软件的本地仓库.当然,我们可以使用 curl 或者 wget 下载任何软件包,然而这些命令并不能下载要求的依赖软件包.你必须去花一些时 ...

  9. 【无法使用yum安装软件】使用yum命令安装软件提示No package numactl.x86_64 available.

    在安装mysql时需要安装numactl.x86_64 使用yum -y install numactl.x86_64时报错 [root@sdp6 mysql]# yum -y install num ...

  10. Android中EditText焦点问题

    https://www.jianshu.com/p/3d31d681f4bc 问题:当EditText失去焦点时做内容校验 场景:用户编辑EditText将内容清空,当点击空白地方时关闭软键盘,同时校 ...