即使采用最佳方法(Java),也超过了时间限制

时间:2018-08-27 18:09:30

标签: java

即使我认为我用最佳方法解决了竞争性编程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);
            }
        }
    }
}

我的问题是:我的方法有什么问题?为什么时间用完了?

2 个答案:

答案 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()函数会再次读取数据。