即使我认为我用最佳方法解决了竞争性编程problem from HackerEarth,所有测试都超过了时间限制。我真的不知道如何进一步优化它,因为这只是一个简单的练习。
我的方法:遍历所有数组成员,而不是将它们添加到存储其出现的HashMap
中。之后,只需读取查询编号并从HashMap
中获取查询编号。
这是我的解决方案:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
class TestClass {
public static void main(String args[]) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int t = Integer.parseInt(br.readLine());
//go through all test cases
for (int i = 0; i < t; i++) {
Map<Integer, Integer> map = new HashMap<>();
String[] inputs = br.readLine().split(" ");
int N = Integer.parseInt(inputs[0]);
int Q = Integer.parseInt(inputs[1]);
inputs = br.readLine().split(" ");
//read array
for (int j = 0; j < N; j++) {
int x = Integer.parseInt(inputs[j]);
Integer value = map.get(x);
//if number is already in hashmap then increment its count
//else put it into the map with a count of 1
if (value == null) {
map.put(x, 1);
} else map.put(x, value + 1);
}
//iterate through the queries and get their occurences from the map
for (int j = 0; j < Q; j++) {
int x = Integer.parseInt(br.readLine());
Integer value = map.get(x);
if (value == null) {
System.out.println(0);
} else System.out.println(value);
}
}
}
}
我的问题是:我的方法有什么问题?为什么时间用完了?
答案 0 :(得分:1)
好,所以问题不是那么明显。我看了看输入文件,它们很大,因此您必须使用一些非常快速的方法来写入控制台(许多测试用例->>许多答案)。您可以为此使用at System.WeakReference.get_Target()
at System.Transactions.Transaction.JitSafeGetContextTransaction(ContextData contextData)
at System.Transactions.Transaction.FastGetTransaction(TransactionScope currentScope, ContextData contextData, Transaction& contextTransaction)
at System.Transactions.Transaction.get_Current()
at NHibernate.Transaction.AdoNetWithDistributedTransactionFactory.EnlistInDistributedTransactionIfNeeded(ISessionImplementor session)
at NHibernate.Impl.SessionImpl.get_PersistenceContext()
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.Save(Object obj)
。
工作解决方案:
PrinteWriter
是的,我知道练习本身并不那么难,但是阅读输入并编写结果是其中的很大一部分,这很奇怪。
答案 1 :(得分:0)
您的方法存在的问题主要是使用BufferedReader,以及随之而来的信息解析。尝试使用扫描仪的方法。
import java.util.*;
class TestClass {
public static void main(String args[] ) throws Exception {
Scanner s = new Scanner(System.in);
int T = s.nextInt();
Map<Integer,Integer> map=new HashMap<Integer,Integer>();
for(int i=0;i<T;i++)
{
StringBuilder sb=new StringBuilder();
int N=s.nextInt();
int Q=s.nextInt();
int[] arr=new int[N];
for(int j=0;j<N;j++)
{
arr[j]=s.nextInt();
if(map.containsKey(arr[j]))
{
map.put(arr[j],map.get(arr[j])+1);
}
else
map.put(arr[j],1);
}
for(int k=0;k<Q;k++)
{
int X=s.nextInt();
if(map.containsKey(X)){
sb.append(map.get(X)+"\n");
}
else{
sb.append(0+"\n");
}
}
System.out.println(sb.toString());
map.clear();
}
}
}
这将消除您执行的许多不必要的解析:
String[] inputs = br.readLine().split(" ");
int N = Integer.parseInt(inputs[0]);
int Q = Integer.parseInt(inputs[1]);
inputs = br.readLine().split(" ");
请查看Scanner vs. BufferedReader,以了解为什么Scanner在这种情况下速度更快。从本质上讲,BufferedReader能够轻松读取行,因此速度更快,但是在此处使用BufferedReader时,则不得不使用Integer.parseInt(...)
和br.readlines().split(" ")
来解析输入中所需的信息;但是,扫描仪具有内置的解析机制,可以异步读取和解析数据。如您所见,此方法在4到8秒内通过了测试。另外,您可以从使用StringBuilder而不是:
Integer value = map.get(x);
if (value == null) {
pr.println(0);
} else pr.println(value);
使用内置方法map.containsKey(x)
。
Scanner用于从流的内容中解析令牌,而BufferedReader只是读取流并且不执行任何特殊操作 解析。
实际上,您可以将BufferedReader传递给扫描仪,作为 要解析的字符。
此外:
另一方面,扫描仪内置有更多的奶酪;它 可以做BufferedReader可以做的所有事情,并且几乎可以做到 效率也是如此。但是,此外,扫描程序还可以解析 使用常规的基本类型和字符串的基础流 表达式。它还可以使用 您选择的定界符。它还可以对 底层流而不考虑定界符!
在必须调用时,运行时有很大差异
inputs = br.readLine().split(" ");
和Integer.parseInt(..)
多次,而不是简单地调用s.nextInt()
。您已经在使用br.readLine()
读取数据,当您调用Integer.parseInt(...)
时,parseInt()
函数会再次读取数据。