题目要求我们将给出的具体某个客人的点单信息进行转换,做一个桌号与菜品点单次数的统计
初步理解:
1、因为是和具体客人信息无关,所有首先统计每个桌点菜的名称和对应的数量,因为最终结果要按照桌号的升序排序,使用TreeMap<Integer,HashMap<String,Integer>> allMap进行存储
2、将所有菜品名称进行统计,使用一个List<String> titleList保存后,再按照题目要求进行字典序排序,最后插入首列关键字"Table"
3、遍历统计的allMap,key就是桌号,之后按照titleList遍历去value里寻找对应的数量
public static List<List<String>> displayTable(List<List<String>> orders) {
// 用于保存最终列表需要的表头,先把菜名存起来,然后再头部插入“Table”关键字
List<String> titleList = new ArrayList<>();
// 以桌号为key,value为以菜名为key,数量为value的hashMap
TreeMap<Integer,HashMap<String, Integer>> allMap = new TreeMap<>();
if (orders == null || orders.size() == 0){
return null;
}
// 遍历统计桌号对应的菜品有哪些,以及菜品对应的数量有多少
for (int i = 0; i < orders.size(); i ++){
List<String> details = orders.get(i);
int num = Integer.parseInt(details.get(1));
String name = details.get(2);
HashMap<String, Integer> foodMap = allMap.getOrDefault(num, new HashMap<>());
int foodNum = foodMap.getOrDefault(name,0);
foodNum ++;
foodMap.put(name, foodNum);
allMap.putIfAbsent(num,foodMap);
if (!titleList.contains(name)){
titleList.add(name);
}
}
// 对菜名列表进行字典序排序
Collections.sort(titleList);
// 头部插入关键字Table
titleList.add(0,"Table");
// 用于保存最终的结果
List<List<String>> lastList = new ArrayList<>();
lastList.add(titleList);
// 开始遍历整个map
Iterator iter = allMap.entrySet().iterator();
while(iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
int key = (int)entry.getKey();
HashMap<String, Integer> valueMap = (HashMap<String, Integer>)entry.getValue();
List<String> list = new ArrayList();
list.add(String.valueOf(key));
// 对整个菜品的list进行遍历,存入具体的数量
for (int i = 1; i < titleList.size(); i++){
String title= titleList.get(i);
int count = valueMap.getOrDefault(title,0);
list.add(String.valueOf(count));
}
lastList.add(list);
}
return lastList;
}
上面的算法在计算过程中要不断去遍历菜单来获取真实数量,很多桌子就点了其中一两道菜,遍历全部菜品是很耗费时间的做法,参考官方题解,我们可以用map将桌号与菜品的名字的列表序号保存下来,之后再统计实际的数量
1、使用TreeMap将桌号与菜品名称按照升序和字典序排序
2、将桌子代表的横坐标与菜品代表的纵坐标构造出来,并保存
3、根据orders把整个桌子对应的菜品数量统计出来
public List<List<String>> displayTable(List<List<String>> orders) {
// 保存桌号与横坐标
TreeMap<Integer,Integer> deskMap = new TreeMap<>();
// 保存菜品与纵坐标
TreeMap<String, Integer> foodMap = new TreeMap<>();
for (List<String> itemList : orders){
deskMap.put(Integer.parseInt(itemList.get(1)),-1);
foodMap.put(itemList.get(2),-1);
}
int[][] infoToInt = new int[deskMap.keySet().size()][foodMap.keySet().size() + 1];
// 根据已经排好序的两个map,确定具体桌号与菜品的坐标
int defaultDeskIndex = -1;
for(Integer deskIndex : deskMap.keySet()){
deskMap.put(deskIndex, ++defaultDeskIndex);
infoToInt[defaultDeskIndex][0] = deskIndex;
}
int defaultFoodIndex = -1;
// 在遍历菜品时,把列表头构造出来
List<String> lineList = new ArrayList<>();
lineList.add("Table");
for(String foodName : foodMap.keySet()){
foodMap.put(foodName, ++defaultFoodIndex);
lineList.add(foodName);
}
for (List<String> itemList : orders){
String foodName = itemList.get(2);
int foodIndex = foodMap.get(foodName);
int deskNum = Integer.parseInt(itemList.get(1));
int deskIndex = deskMap.get(deskNum);
// 这里因为保存了桌号所以要加1
infoToInt[deskIndex][foodIndex + 1] = infoToInt[deskIndex][foodIndex + 1] + 1;
}
List<List<String>> resultList = new ArrayList();
resultList.add(lineList);
for (int i = 0; i < infoToInt.length; i ++){
List<String> list = new ArrayList();
for (int j = 0; j < infoToInt[i].length; j++){
list.add(String.valueOf(infoToInt[i][j]));
}
resultList.add(list);
}
return resultList;
}
题目错点:
1、不熟悉TreeMap的遍历和字符串转整型的Integer.praseInt()方法,平时都是编译器提醒,自己写的时候会忘记
2、第一遍提交的时候,因为桌号使用的String类型,排序按照字典序10因为是1开头比5要小,所以最后的结果是10桌在前