已超出Java问题时间限制问题
Im编码问题(参考--http://www.codechef.com/FEB11/problems/THREECLR/) 下面是我的代码已超出Java问题时间限制问题,java,algorithm,execution-time,Java,Algorithm,Execution Time,Im编码问题(参考--http://www.codechef.com/FEB11/problems/THREECLR/) 下面是我的代码 import java.io.*; import java.util.*; public class Main { static String ReadLn (int maxLg) // utility function to read from stdin { byte lin[] = new byte [maxLg];
import java.io.*;
import java.util.*;
public class Main {
static String ReadLn (int maxLg) // utility function to read from stdin
{
byte lin[] = new byte [maxLg];
int lg = 0, car = -1;
String line = "";
try
{
while (lg < maxLg)
{
car = System.in.read();
if ((car < 0) || (car == '\n')) break;
lin [lg++] += car;
}
}
catch (IOException e)
{
return (null);
}
if ((car < 0) && (lg == 0)) return (null); // eof
return (new String (lin, 0, lg));
}
public static boolean iscontains(HashMap<Integer,HashSet<Integer>> resultmap,HashSet<Integer> b, int index)
{
boolean result=false;
for(Iterator<Integer> iter = b.iterator();iter.hasNext();)
{ int tmp=Integer.valueOf(iter.next().toString());
if(resultmap.get(index).contains(tmp))
result=true;
}
return result;
}
public static void main(String[] args) throws InterruptedException, FileNotFoundException {
try {
HashMap<Integer,HashSet<Integer>> pairlist = new HashMap<Integer,HashSet<Integer>>();
String input=null;
StringTokenizer idata;
int tc=0;
input=Main.ReadLn(255);
tc=Integer.parseInt(input);
while(--tc>=0)
{
input=Main.ReadLn(255);
idata = new StringTokenizer (input);idata = new StringTokenizer (input);
int dishnum= Integer.parseInt(idata.nextToken());
int pairnum= Integer.parseInt(idata.nextToken());
while (--pairnum>=0)
{
input=Main.ReadLn(255);
idata = new StringTokenizer (input);idata = new StringTokenizer (input);
int dish1=Integer.parseInt(idata.nextToken());
int dish2=Integer.parseInt(idata.nextToken());
if(pairlist.containsKey((Integer)dish1))
{
HashSet<Integer> dishes=new HashSet<Integer>();
dishes=pairlist.get(dish1);
dishes.add(dish2);
pairlist.put(dish1, dishes);
}
else
{
HashSet<Integer> dishes=new HashSet<Integer>();
dishes.add(dish2);
pairlist.put(dish1, dishes);
}
}
int maxrounds=1;
HashMap<Integer,HashSet<Integer>> resultlist = new HashMap<Integer,HashSet<Integer>>();
HashSet<Integer> addresult=new HashSet<Integer>();
addresult.add(1);
resultlist.put(1,addresult);
System.out.print("1");
for(int i=2;i<=dishnum;i++)
{
boolean found_one=false;
boolean second_check=false;
int minroundnum=maxrounds;
boolean pairlistcontains=false;
pairlistcontains=pairlist.containsKey(i);
for(int j=maxrounds;j>=1;j--)
{
if(!found_one){
if(pairlistcontains)
{
if(!iscontains(resultlist,pairlist.get((Integer) i),j))
{
for(Iterator<Integer> resultiter = resultlist.get(j).iterator();resultiter.hasNext();)
{
if(pairlist.get(resultiter.next()).contains(i))
second_check=true;
}
if(second_check==false)
{
found_one=true;
minroundnum=j;
j=0;
//second_check=false;
}
}
}
else
{
for(Iterator<Integer> resultiter = resultlist.get(j).iterator();resultiter.hasNext();)
{
if(pairlist.get(resultiter.next()).contains(i))
second_check=true;
}
if(second_check==false)
{
found_one=true;
minroundnum=j;
j=0;
//second_check=false;
}
}
second_check=false;
}
}
if((minroundnum==maxrounds)&&(found_one==false))
{
++minroundnum;
++maxrounds;
}
else
{
found_one=false;
}
HashSet<Integer> add2list=new HashSet<Integer> ();
if(resultlist.containsKey(minroundnum))
{
add2list=resultlist.get(minroundnum);
add2list.add(i);
}
else
{
add2list.add(i);
}
resultlist.put(minroundnum,add2list);
System.out.print(" ");
System.out.print(minroundnum);
}
if((tc !=-1))
System.out.println();
}
}
catch(Exception e){System.out.println(e.toString());}
}}
我的代码花了71052毫秒在上面脚本提供的输入上执行。我现在必须把执行时间降到最短8000毫秒。
我正在尝试按照rfeak的建议替换HashMaps和HashSet,我还想知道在这种情况下,记忆是否会有所帮助。请告知
编辑2--
用数组重新编码我的算法似乎奏效了。不过,在不同的时间重新提交相同的代码给了我一个可接受的解决方案,并且超出了时间限制:D我想到了另一种使用hashmaps进行进一步优化的方法。
谢谢大家的帮助 在本地运行时,您的程序使用了多少内存 如果他们在没有足够内存的情况下运行Java程序,您可能会花费大量时间尝试垃圾收集。这可能会破坏你的1秒时间 如果你需要节省时间和内存(待定),我有两个建议 将
哈希集
替换为位集
。类似的接口,更快的实现,使用更少的内存。特别是我在问题中看到的数字
将
Map
替换为X[]
-整数键可以是数组中的int(原语)索引。同样,更快、更小。您是否考虑过他们输入的数据量要大得多,而您的代码处理时间太长?您知道他们提交的数据集有多大吗?你能得到那个数据集吗?我猜你期望的是一个不会发生的输入,或者有一个导致你的程序进入无限循环的输入。你能解释一下代码背后的想法和它的复杂性吗?您是否尝试过在没有try/catch
行的情况下提交代码?您不应该向在线法官提交带有错误检查的代码。这只会让你的程序慢下来,而且一个值得尊敬的法官永远不会给你提供坏数据。当没有异常被捕获时,try/catch块是免费的,不是吗。他不会进行错误检查,他会(有点)吞咽异常。一定要去掉HashSet
和Map
。问题中给出的数字都足够小,一个数组(或者位集
可能比这个更快,但我认为这里不需要它)就足够了。谢谢你的建议。我对位集的实现不是很清楚。JavaDoc说它们包含数字的位表示,并支持对其进行逻辑运算。我主要不想对输入数据进行这种操作,但如果这是最实用和最好的方法,我肯定会尝试一下。请给出建议。@JCoder-忽略它如何描述它的内部表示。最好将一个位集看作一组int(原语)。该集合要么包含整数,要么不包含整数。若要查看是否有,请调用BitSet.get(someInt)。要将整数放入集合,请调用BitSet.set(someInt)。这样,它的行为就像一个集合。。。现在,如果你真的对为什么它比一个集合小感兴趣,我可以补充我的答案。
import random
filename="input.txt"
file=open(filename,'w')
file.write("50")
file.write("\n")
for i in range(0,50):
file.write("500 10000")
file.write("\n")
for j in range(0,10000):
file.write(str(random.randrange(1,501))+" "+str(random.randrange(1,501)))
file.write("\n")
file.close()