Java [Hackerrank][性能改进]类似目的地

Java [Hackerrank][性能改进]类似目的地,java,algorithm,performance,Java,Algorithm,Performance,我目前正在解决我在Hackerrank上发现的一个难题,我需要代码优化/性能部门的一些帮助。我已经设法让代码正常工作并返回正确的结果,但在最终测试用例中失败,出现了超时错误。输入非常大,这就解释了为什么代码花费的时间比预期的要长 问题陈述: 我曾试图用不同的方法来修剪我的(中间)结果集,但却无法想出一些我还没有的东西。我相信find函数需要更多的调整。我已经尽了最大努力减少递归函数必须采用的路径数,但最终,它必须查看每个目的地,以得到正确的结果。但是,如果目的地之间的公共标记数低于min限制,

我目前正在解决我在Hackerrank上发现的一个难题,我需要代码优化/性能部门的一些帮助。我已经设法让代码正常工作并返回正确的结果,但在最终测试用例中失败,出现了超时错误。输入非常大,这就解释了为什么代码花费的时间比预期的要长

问题陈述:


我曾试图用不同的方法来修剪我的(中间)结果集,但却无法想出一些我还没有的东西。我相信
find
函数需要更多的调整。我已经尽了最大努力减少递归函数必须采用的路径数,但最终,它必须查看每个目的地,以得到正确的结果。但是,如果目的地之间的公共标记数低于
min
限制,我确实终止了递归路径。这里还有什么我可以做的吗

我的代码如下:-

  static class Destination {
    String dest;
    List<String> tags;

    public Destination(String dest, List<String> tags) {
      this.dest = dest;
      this.tags = tags;
    }

    @Override
    public String toString() {
      return dest;
    }
  }

  static List<Destination> allDest = new ArrayList<Destination>();
  static int min;
  static Set<String> keysTracker = new HashSet<String>();
  static Set<String> tagsTracker = new HashSet<String>();
  static Map<String, List<String>> keysAndTags = new HashMap<String, List<String>>();

  static void find(List<String> commonKey, List<String> commonTags, int index) {

    if (index >= allDest.size())
      return;

    if (commonTags.size() < min)
      return;

    if (tagsTracker.contains(commonTags.toString()) || keysTracker.contains(commonKey.toString())) {
      return;
    }

    String dest = allDest.get(index).dest;
    commonKey.add(dest);

    for (int i = index + 1; i < allDest.size(); ++i) {

      List<String> tempKeys = new ArrayList<String>(commonKey);
      List<String> tags = allDest.get(i).tags;
      List<String> tempTags = new ArrayList<String>(commonTags);
      tempTags.retainAll(tags);

      find(tempKeys, tempTags, i);

      if (tempTags.size() >= min) {
        if (!tagsTracker.contains(tempTags.toString())
            && !keysTracker.contains(tempKeys.toString())) {
          tagsTracker.add(tempTags.toString());
          keysTracker.add(tempKeys.toString());

          StringBuilder sb = new StringBuilder();
          for (int j = 0; j < tempKeys.size(); ++j) {
            sb.append(tempKeys.get(j));
            if (j + 1 < tempKeys.size())
              sb.append(",");
          }
          keysAndTags.put(sb.toString(), tempTags);
        }
      }
    }

  }

  public static void main(String[] args) {
    init();
    sort();
    calculate();
    answer();
  }

  static void init() {
    Scanner s = new Scanner(System.in);

    min = s.nextInt();
    s.nextLine();

    String line;
    while (s.hasNextLine()) {
      line = s.nextLine();
      if (line.isEmpty())
        break;
      String[] tokens = line.split(":");

      String dest = tokens[0];

      tokens = tokens[1].split(",");

      List<String> tags = new ArrayList<String>();
      for (int j = 0; j < tokens.length; ++j)
        tags.add(tokens[j]);
      Collections.sort(tags);

      Destination d = new Destination(dest, tags);
      allDest.add(d);
    }

    s.close();
  }

  static void sort() {
    Collections.sort(allDest, new Comparator<Destination>() {

      @Override
      public int compare(Destination d1, Destination d2) {
        return d1.dest.compareTo(d2.dest);
      }

    });
  }

  static void calculate() {
    for (int i = 0; i < allDest.size() - 1; ++i) {

      find(new ArrayList<String>(), new ArrayList<String>(allDest.get(i).tags), i);

    }
  }

  static void answer() {
    List<Map.Entry<String, List<String>>> mapInListForm = sortAnswer();

    for (Map.Entry<String, List<String>> entry : mapInListForm) {
      System.out.print(entry.getKey() + ":");
      for (int i = 0; i < entry.getValue().size(); ++i) {
        System.out.print(entry.getValue().get(i));
        if (i + 1 < entry.getValue().size())
          System.out.print(",");
      }
      System.out.println();
    }
  }

  static List<Map.Entry<String, List<String>>> sortAnswer() {
    List<Map.Entry<String, List<String>>> mapInListForm =
        new LinkedList<Map.Entry<String, List<String>>>(keysAndTags.entrySet());
    Collections.sort(mapInListForm, new Comparator<Map.Entry<String, List<String>>>() {
      public int compare(Map.Entry<String, List<String>> e1, Map.Entry<String, List<String>> e2) {

        if (e1.getValue().size() > e2.getValue().size()) {
          return -1;
        } else if (e1.getValue().size() < e2.getValue().size()) {
          return 1;
        }
        return e1.getKey().compareTo(e2.getKey());

      }
    });
    return mapInListForm;
  }
静态类目的地{
字符串dest;
列出标签;
公共目的地(字符串目的地、列表标记){
this.dest=dest;
this.tags=标签;
}
@凌驾
公共字符串toString(){
返回目的地;
}
}
静态列表allDest=newarraylist();
静态int-min;
静态设置keysTracker=newhashset();
static Set tagsTracker=new HashSet();
静态映射keysAndTags=newhashmap();
静态void查找(列表commonKey、列表commonTags、int索引){
如果(索引>=allDest.size())
返回;
if(commonTags.size()=min){
如果(!tagsTracker.contains(testtags.toString())
&&!keysTracker.contains(tempKeys.toString())){
tagsTracker.add(testags.toString());
添加(tempKeys.toString());
StringBuilder sb=新的StringBuilder();
对于(int j=0;je2.getValue().size()){
返回-1;
}else if(e1.getValue().size()

非常感谢您的帮助。谢谢

经过一点选择性分析后,我成功地解决了这个问题。看来我最初的预感是对的。问题与算法无关,而与我使用的数据结构有关!罪犯使用了
查找
方法。具体来说,在两个
列表上调用
retainal
方法时。我忘记了迭代两个
列表需要O(n^2)时间。这就是它慢的原因。然后我将
list
改为
HashSet
。我们大多数人都知道,
HashSet
在访问其值时具有O(1)时间复杂性。
retainAll
方法保留了下来,但是我们现在找到的不是两个
列表之间的交集,而是两个
集合之间的交集!这使得总运行时间缩短了几秒钟,所有测试都通过了。:)

find
方法现在如下所示:-

  static void find(List<String> commonKey, List<String> commonTags, int index) {

    if (index >= allDest.size())
      return;

    if (commonTags.size() < min)
      return;

    if (tagsTracker.contains(commonTags.toString()) || keysTracker.contains(commonKey.toString())) {
      return;
    }

    String dest = allDest.get(index).dest;
    commonKey.add(dest);

    for (int i = index + 1; i < allDest.size(); ++i) {

      List<String> tempKeys = new ArrayList<String>(commonKey);
      List<String> tags = allDest.get(i).tags;
      Set<String> tempTagsSet1 = new HashSet<String>(commonTags);
      Set<String> tempTagsSet2 = new HashSet<String>(tags);
      tempTagsSet1.retainAll(tempTagsSet2);
      List<String> tempTags = new ArrayList<String>(tempTagsSet1);

      if (tempTags.size() >= min)
        Collections.sort(tempTags);

      find(tempKeys, tempTags, i);

      if (tempTags.size() >= min) {
        if (!tagsTracker.contains(tempTags.toString())
            && !keysTracker.contains(tempKeys.toString())) {
          tagsTracker.add(tempTags.toString());
          keysTracker.add(tempKeys.toString());

          StringBuilder sb = new StringBuilder();
          for (int j = 0; j < tempKeys.size(); ++j) {
            sb.append(tempKeys.get(j));
            if (j + 1 < tempKeys.size())
              sb.append(",");
          }
          keysAndTags.put(sb.toString(), tempTags);
        }
      }
    }

 }
static void find(列出commonKey、列出commonTags、int索引){
如果(索引>=allDest.size())
返回;
if(commonTags.size()