Java 多條件復雜排序小結


前言

今天下午做了拼多多在牛客網上的在線筆試題,感覺自己的智商被鄙視到了···不過其中一道題的某一部分引起了我極大的興趣,感覺可以總結一下,做好積累~

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

 



這里面最復雜的就是第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;
} 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM