【问题标题】:Merging two sorted ArrayLists合并两个排序的 ArrayList
【发布时间】:2017-08-28 20:30:42
【问题描述】:

我应该创建一个方法,将两个给定的预先排序的字符串数组列表合并为一个。所有这些都必须在一个循环中完成。我采取的方法是比较每个索引处的两个 ArrayList,并根据这些比较按字母顺序添加它们。这样做的问题是,如果给定两个 ArrayList ["Bob", "Jill"] 和 ["Watson", "Zane"],输出将是 ["Bob", "Watson", "Jill", "赞恩”]。这显然没有排序。

话虽如此,我知道问题出在哪里,只是不知道如何解决它。

代码:

public static ArrayList<String> merge(ArrayList<String> al1, ArrayList<String> al2){
  ArrayList<String> al = new ArrayList<String> (al1.size() + al2.size());
  for (int i = 0; i < Math.max(al1.size(), al2.size()); i++) { // Loops until max size of the two arraylists is reached
      if (i < al1.size() && i < al2.size()) { // Checks if the index is still in range of both arraylists
          if (al1.get(i).compareTo(al2.get(i)) < 0) { // Compares the two arraylists at the same index
              al.add(al1.get(i));
              al.add(al2.get(i));
          } else {
              al.add(al2.get(i));
              al.add(al1.get(i));
          }
      } else if (i < al1.size() && i > al2.size()) { // Checks if the index is greater than the size of al2
          al.add(al1.get(i));
      } else { // Anything else, just add al2
          al.add(al2.get(i));
      }
  }
  return al;

【问题讨论】:

  • merge algorithms 上的维基百科文章将是一个好的开始,如果您还没有看到的话。
  • 您总是在比较两个列表中相同索引处的元素。正如您所发现的,这根本不起作用。您需要跟踪正在考虑添加到合并列表中的当前元素的两个列表中的单独位置。当您到达一个列表的末尾时,您需要将另一个列表的所有元素附加到合并结果中。
  • 从技术上讲,它是 3 个循环,其中使用了 2 个。当到达任何一个预排序数组列表的末尾时,合并循环停止,然后是一个复制循环来复制剩余的预排序数组的其余部分(假设 Java 没有等效的 memcpy 或切片)。这可以使用 if 语句折叠成一个循环。

标签: java sorting arraylist merge


【解决方案1】:
public static ArrayList<Double> merge(ArrayList<Double> a, ArrayList<Double> b) {

    ArrayList<Double> toReturn = new ArrayList<Double>();
    int a_ = 0;
    int b_ = 0;

    for(int j = 0; j < a.size() + b.size(); j++) {
        if(a_ == a.size())
            toReturn.add(b.get(b_++));
        else if(b_ == b.size())
            toReturn.add(a.get(a_++));
        else if(a.get(a_).compareTo(b.get(b_)) < 0)
            toReturn.add(a.get(a_++));
        else
            toReturn.add(b.get(b_++));
    }

    return toReturn;
}

【讨论】:

    【解决方案2】:

    您正在使用一个索引i 来同时索引a1a2,这意味着您不能独立地浏览这两个列表。正如您所注意到的,应该通过从第一个列表中获取所有三个元素并然后从第二个列表中获取元素来合并一对列表,例如[1, 2, 3][4, 5, 6]。通过同时遍历两个列表是不可能的。

    而是跟踪两个独立的指标,例如 i1i2,并独立递增它们。在每次迭代中确定哪个索引更小,添加该值并增加该索引。一旦您到达一个列表或另一个列表的末尾,您只需排空剩余列表。

    【讨论】:

      【解决方案3】:

      你应该看看合并排序算法的合并步骤: https://en.wikipedia.org/wiki/Merge_sort

      总而言之,你应该有类似的东西:

      int i = 0;
      int j = 0;
      while (i < a.size() && j < b.size()) {
          if (a.get(i).compareTo(b.get(j)) <= 0) {
              result.add(a.get(i));
              ++i;
          } else {
              result.add(b.get(j));
              ++j;
          }
      }
      
      for (; i < a.size(); ++i) {
          result.add(a.get(i));
      }
      
      for (; j < a.size(); ++j) {
          result.add(b.get(j));
      }
      
      return result;
      

      没有测试,但结果应该是一样的

      【讨论】:

        猜你喜欢
        • 2015-10-28
        • 2017-04-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-29
        • 1970-01-01
        • 1970-01-01
        • 2021-05-01
        相关资源
        最近更新 更多