题目
链接:https://www.nowcoder.com/questionTerminal/67df1d7889cf4c529576383c2e647c48
来源:牛客网
这个程序,看似简单,实际上考了很多细节,我花了很多时间来做,不是被算法
难住,而是在细节上出了很多漏洞。整体要求很快就实现了,而一直报答案错误
,第一个原因,只能是8条记录以内,我全部输出;第二个原因,题目要求稳定排
序,我排出来了,却颠倒了关键字的顺序;第三个原因,我以为都OK了,却忘了
文件名16个字符的要求。三个原因我找了很久,我以为我是理解题目错误,实际
上就是忽略了细节,造成浪费了大量的时间。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
public class Main {
static class EFile{
public String name;
public int line;
public int num;
public int order;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + line;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
EFile other = (EFile) obj;
if (this == obj){ other.num++; return true;
}
if (getClass() != obj.getClass())
return false;
if (line != other.line){
return false;
}
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name)){
return false;
} other.num++; return true;
}
}
public static void main(String[] args){
Set<EFile> set = new HashSet<EFile>();
Scanner in = new Scanner(System.in);
int j = 0;
while (in.hasNext()) {
String s = in.next();
int line = in.nextInt();
EFile file = new EFile();
int bi = s.lastIndexOf("\\");
file.name = s.substring(bi+1);
file.line = line;
if(set.add(file)){
file.num++;
file.order = j;
j++;
}
}
in.close();
List<EFile> list = new ArrayList<EFile> (set);
Comparator<EFile> cmp = new Comparator<EFile>() {
@Override
public int compare(EFile o1, EFile o2) {
return o1.num - o2.num ==0 ?(o1.order-o2.order):(o2.num-o1.num);
}
};
Collections.sort(list,cmp);
StringBuffer sb = new StringBuffer();
for(int i = 0; i < (list.size() > 8 ? 8 : list.size()); i ++){
StringBuffer result;
EFile eFile = list.get(i);
if(eFile.name.length() > 16){
result =new StringBuffer(eFile.name.substring(eFile.name.length() - 16, eFile.name.length()));
}else{
result =new StringBuffer(eFile.name);
}
result.append(" ").append(eFile.line).append(" ").append(eFile.num);
System.out.println(result.toString());
}
}
}
链接:https://www.nowcoder.com/questionTerminal/67df1d7889cf4c529576383c2e647c48
来源:牛客网
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
//创建接受键盘录入对象
Scanner cin = new Scanner(System.in);
// 接受文件名称或者文件路径
String file = null;
// 获取文件路径 最后一个“\” 下标索引
int lastIndex = 0;
// 获取文件名称
// 接受错误出现的行号
int errorLine = 0;
// 创建一个HashMap<ErrLog>
HashMap<String, ErrLog> hashMap = new HashMap<String, ErrLog>();
ErrLog errLog = null;
String key = null;
StringBuilder sbBuilder = new StringBuilder();
while (cin.hasNext()) {
// 第一个参数为文件名称或文件路径
file = cin.next();
// 获取错误行号
errorLine = cin.nextInt();
// 获取最后一个'\'的索引
lastIndex = file.lastIndexOf('\\');
// 如果没有找到说明不是路径,直接返回文件名
// 是路径 就截取\后面的字符串作为文件名
sbBuilder
.append(lastIndex < 0 ? file : file.substring(lastIndex + 1))
.append(" ").append(errorLine);
key = sbBuilder.toString();
sbBuilder.setLength(0);
// 将错误记录添加进hashMap 中
errLog = hashMap.get(key);
if (errLog == null) {
// 如果不存在,new 一个并添加进去
hashMap.put(key, new ErrLog(key, 1));
} else errLog.size++; //存在,就将错误次数累加
}
cin.close();
// ----------以上就是统计错误信息,下面是取值------------------
ArrayList<ErrLog> list = new ArrayList<ErrLog>(hashMap.values());
// 根据 错误次数比较,将错误次数多的放前面,如果错误次数一致,将出现顺序早的放到前面 进行排序
Comparator<ErrLog> cmp = new Comparator<ErrLog>() {
@Override
public int compare(ErrLog o1, ErrLog o2) {
return o2.size - o1.size == 0 ? (o1.queueMark - o2.queueMark)
: o2.size - o1.size;
}
};
Collections.sort(list, cmp);
// 取出前8个,并输出
int lens = 8 > list.size() ? list.size() : 8;
for (int i = 0; i < lens; i++) {
//这里文件名如果大于16位 还需要截取文件名16位 + 行号 输出
errLog = list.get(i);
//这样就获取到了分界符' '的索引了,然后往前推16位就是我们要输出的文件名了
lastIndex = errLog.name.lastIndexOf(" ");
lastIndex = lastIndex - 16 < 0 ? 0 : lastIndex - 16;
// 获取文件名并输出
System.out.println((lastIndex == 0 ? errLog.name : errLog.name
.substring(lastIndex)) + " " + errLog.size);
}
}
}
class ErrLog {
// 此类并不标准,仅方便此题目实现而已
static int mark; //辅助实现字段queueMark按出现顺序自增
String name;//fileName 存储错误的文件名称,由完整的文件名,与错误行号组成。
int queueMark; // 标记出现的顺序
int size; // 统计出现错误的次数
public ErrLog(String name, int size){
super();
this.name = name;
this.queueMark = mark++;
this.size = size;
}
}
链接:https://www.nowcoder.com/questionTerminal/67df1d7889cf4c529576383c2e647c48
来源:牛客网
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Map<String, Integer> map = new LinkedHashMap<>();
while (sc.hasNextLine()) {
String s = sc.nextLine();
if(s == null || "".equals(s)) break;
String[] split = s.split("\\s");
String key = split[0].substring(split[0].lastIndexOf('\\') + 1) + " " + split[1];
map.put(key, map.containsKey(key) ? map.get(key) + 1 : 1);
}
List<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
return o2.getValue().compareTo(o1.getValue());
}
});
for (int i = 0; i < 8; i ++) {
String[] split = list.get(i).getKey().split("\\s");
if(split[0].length() > 16) split[0] = split[0].substring(split[0].length() - 16);
System.out.println(split[0] + " " + split[1] + " " + list.get(i).getValue());
}
}
}
链接:https://www.nowcoder.com/questionTerminal/67df1d7889cf4c529576383c2e647c48
来源:牛客网
import java.util.*;
/**
* 华为02-简单错误记录
*
* 第一次思路:因为一直在想如何使文件名如何对应多个行数的解决方法,卡了好多大会
* 就这样越想越复杂,但是基本思路有了。
* 就是用一个map记录文件名及其对应的在list中索引(由自增序号自动生成)。
* list是用来存放新建的不重复的错误。
* 这样我们每次对于一个新的错误,首先看map中是否有
* 若有,我们通过索引找到list中的对应node,更新其次数
* 若没有,map中存放文件名及其自增序号,同时在list中添加一条新的错误记录
* 最后我们排序,取出前8个即可。
*
* 技巧:
* 1.如何解决文件名如何对应多个行数
* 我擦,直接令文件名加上行数当成key就可以了啊!!!太妙了
* 2.我们只需在list中添加错误记录时,注意要对超过16的处理一下
* 3.Collection.sort()可以使用lambda表达式哦
* Create by Special on 2018/2/14 22:01
*/
public class Main {
static Map<String, Integer> fileOriginName;
static List<Node> nodes = new ArrayList<>();
static class Node{
String name;
int count;
public Node(String name){
this.name = name;
this.count = 1;
}
public void add(int value){
count += value;
}
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
fileOriginName = new HashMap<>();
String fileName;
int count = 0, index;
while(input.hasNext()){
fileName = input.nextLine();
fileName = fileName.substring(fileName.lastIndexOf('\\') + 1);
if(fileOriginName.containsKey(fileName)){
nodes.get(fileOriginName.get(fileName)).add(1);
} else{
fileOriginName.put(fileName, count++);
index = fileName.indexOf(' ');
fileName = index > 16 ? fileName.substring(index - 16) : fileName;
nodes.add(new Node(fileName));
}
}
Collections.sort(nodes, (node1, node2) -> {
return node2.count - node1.count;
});
Node node;
for(int i = 0; i < Math.min(8, nodes.size()); i++){
node = nodes.get(i);
System.out.println(node.name + " " + node.count);
}
}
}
链接:https://www.nowcoder.com/questionTerminal/67df1d7889cf4c529576383c2e647c48
来源:牛客网
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Scanner;
class ByValueComparator implements Comparator<String>{
HashMap<String, Integer> base_map;
public ByValueComparator(HashMap<String,Integer> map) {
// TODO Auto-generated constructor stub
this.base_map = map;
}
@Override
public int compare(String str1, String str2) {
// TODO Auto-generated method stub
if(!base_map.containsKey(str1) || !base_map.containsKey(str2)){
return 0;
}
if(base_map.get(str1) < base_map.get(str2)){
return 1;
}else{
//相等也要返回-1,否则在排序时不会把相等的值放到TreeMap中,若=0则新值替代原值
//为何相等是返回-1不是返回1,根据情况而定,返回1代表新值放到旧值前面,-1代表新值放在旧值后面
return -1;
}
}
}
public class juan1_q2 {
public static void main(String[] ags){
HashMap<String, Integer> recMap = new HashMap<String, Integer>();
Scanner input = new Scanner(System.in);
String file = "";
int errorLine = 0;
int lastIndex = 0;
String recName = null;
while(input.hasNext()){
file = input.next();
errorLine = input.nextInt();
lastIndex = file.lastIndexOf("\\");
recName = (lastIndex < 0)?file:file.substring(lastIndex+1)+" "+errorLine;
int count = 0;
if(!recMap.containsKey(recName)){
recMap.put(recName, 1);
}else{
count = recMap.get(recName);
recMap.put(recName, count+1);
}
}
input.close();
//--------以上统计,以下排序取值-------------
ArrayList<String> keys = new ArrayList<String>(recMap.keySet());
ByValueComparator bvc = new ByValueComparator(recMap);
Collections.sort(keys, bvc);
for(int i = 0;i < (keys.size() > 8?8:keys.size());i++){
String key = keys.get(i);
StringBuilder res = new StringBuilder();
lastIndex = key.lastIndexOf(" ");
int value = recMap.get(key);
if(lastIndex > 16){
res.append(key.substring(lastIndex-16));
}else{
res.append(key);
}
res.append(" "+value);
System.out.println(res.toString());
}
}
}
以上代码有两个问题:
1.comparator理解问题,返回1代表str1会放在str2后面,-1代表str1放在str2前面,若相等应该是返回0.
2.没有考虑输入顺序的排序,因此要使用LinkedHashMap代替HashMap来保存输入顺序的信息
修改代码通过,如下:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Scanner;
class ByValueComparator implements Comparator<String>{
HashMap<String, Integer> base_map;
public ByValueComparator(HashMap<String,Integer> map) {
// TODO Auto-generated constructor stub
this.base_map = map;
}
@Override
public int compare(String str1, String str2) {
// TODO Auto-generated method stub
if(!base_map.containsKey(str1) || !base_map.containsKey(str2)){
return 0;
}
if(base_map.get(str1) < base_map.get(str2)){
return 1;
}else if(base_map.get(str1) > base_map.get(str2)){
//从大到小排序,因此若str1<str2,则返回1,即str2会排在str1前面;str1>str2,返回-1,则str1排在str2前面
//从小到大排序,-1代表str1<str2;0代表==,不动位置;1代表str1>str2,str1放在str2后。
return -1;
}else{
return 0;
}
}
}
public class juan1_q2 {
public static void main(String[] ags){
LinkedHashMap<String, Integer> recMap = new LinkedHashMap<String, Integer>();
Scanner input = new Scanner(System.in);
String file = "";
int errorLine = 0;
int lastIndex = 0;
String recName = "";
while(input.hasNext()){
file = input.next();
errorLine = input.nextInt();
lastIndex = file.lastIndexOf("\\");
recName = (lastIndex < 0)?file:file.substring(lastIndex+1)+" "+errorLine;
int count = 0;
if(!recMap.containsKey(recName)){
recMap.put(recName, 1);
}else{
count = recMap.get(recName);
recMap.put(recName, count+1);
}
}
input.close();
//--------以上统计,以下排序取值-------------
ArrayList<String> keys = new ArrayList<String>(recMap.keySet());
System.out.println(keys.toString());
ByValueComparator bvc = new ByValueComparator(recMap);
Collections.sort(keys, bvc);
System.out.println(keys.toString());
for(int i = 0;i < (keys.size() > 8?8:keys.size());i++){
String key = keys.get(i);
StringBuilder res = new StringBuilder();
lastIndex = key.lastIndexOf(" ");
int value = recMap.get(key);
if(lastIndex > 16){
res.append(key.substring(lastIndex-16));
}else{
res.append(key);
}
res.append(" ").append(value);
System.out.println(res.toString());
}
}
}
我和你写的一样,但是因为同一个文件名和行号被put进去多次,而linkedhashmap里面就是最近一次插入的相对顺序,而不是第一次插入的相对顺序,所以是不对的
可以改参数
链接:https://www.nowcoder.com/questionTerminal/67df1d7889cf4c529576383c2e647c48
来源:牛客网
package nowcoder.record;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
List list = new ArrayList();
while (sc.hasNext()) {
String line = sc.nextLine();
String[] arr = line.split(" ");
String path = arr[0]; // 路径
int lineNum = Integer.valueOf(arr[1]); // 行号
String fileName = path;
if (path.contains("\\")) {
fileName = path.substring(path.lastIndexOf("\\") + 1); // 截取文件名
}
String key = fileName + " " + lineNum;
Iterator it = list.iterator();
boolean flag = false;
while (it.hasNext()) {
Model model = it.next();
if (model.getKey().equals(key)) {
model.setCount(model.getCount() + 1);
flag = true;
}
}
if (!flag) {
Model model = new Main().new Model(key, 1);
list.add(model);
}
}
// System.out.println("origin:");
// for (Model model : list) {
// System.out.println(model.getKey() + " " + model.getCount());
// }
// 下面排序并輸出
Collections.sort(list, new Comparator() {
public int compare(Model o1, Model o2) {
// TODO Auto-generated method stub
return o2.getCount() - o1.getCount();
}
});
// System.out.println("last:");
//超过16个字符的文件名称,只记录文件的最后有效16个字符;(如果文件名不同,而只是文件名的后16个字符和行号相同,也不要合并)
//最多输出8条记录
for (int i = 0; i < list.size() && i < 8; i++) {
Model model = list.get(i);
String temp = model.getKey();
String[] arrs = temp.split(" ");
String name = arrs[0];
int c = Integer.valueOf(arrs[1]);
name = name.length() > 16 ? name.substring(name.length() - 16)
: name;
temp = name + " " + c;
System.out.println(temp + " " + model.getCount());
}
}
class Model {
public Model(String key, int count) {
super();
this.key = key;
this.count = count;
}
String key;
int count;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
}