【问题标题】:Comparing and sorting in javajava中的比较和排序
【发布时间】:2012-01-19 07:45:54
【问题描述】:

我在 Java 中有 2 个数据数组。根据第一个数组的顺序,我必须对下一个数组进行排序。 例如 -

String[] Array1 = {"EUROPE","MIDDLEEAST","OTHERs","AUSTRALIA"};
String[] Array2 = {"MIDDLEEAST","EUROPE","AUSTRALIA","OTHERs","ASIA","EUROPE"};

我的输出应该是这样的:

{"EUROPE","EUROPE","MIDDLEEAST","OTHERs","AUSTRALIA","ASIA"}

最好的方法是什么?

【问题讨论】:

  • 一切都是有道理的,直到你得到你的例子。 Array1 的排序结果如何以 Array2 的方式排序?
  • 它们是 2 个不同的数组。 resultArray 是排序后的,不是 Array2。Array1 和 Array2 中的元素不同。
  • 看来你只是用第一个字符来确定顺序???并且该顺序取决于 array1.... 这不是排序,这更像是映射。
  • 这是一个脑筋急转弯吗? o-o
  • 要对示例中的 Array1 进行排序,我只需要交换前两个元素。但是您的 resultArray 是通过交换第一个和第三个元素从 Array2 获得的。你试图完成的逻辑是什么?

标签: java sorting compare


【解决方案1】:

要进行排序,您需要定义排序顺序,以便给定元素 A 和 B,您可以轻松确定 A 应该在排序列表中排在 B 之前还是之后。

这个概念是用 Java 中的 Comparator 概念形式化的。

在这种情况下,排序顺序由列表中元素的顺序定义。最简单的方法是给 A 和 B 在原始列表中找到它们中的每一个,记下找到的索引,然后比较索引以找出哪个先出现。

根据您的数据大小,这可能会太慢。然后,您可以创建一个 HashMap<String,Long>,它保存 Array1 中给定字符串的索引。在这里它将保存“DEF”->0、“ABC”->1、“XYZ”->2。

【讨论】:

  • 从空间的角度来看,使用所有 array1 元素的位置分配哈希表似乎效率低下。此外,如果 array1 包含重复元素,它将失败。
  • @DilumRanatunga 如果 array1 包含重复元素,您将如何定义排序顺序?关于效率低下,您还会如何加快流程?
  • 在排序中,有一个术语“稳定”。稳定的排序不会交换等价元素的顺序。一些排序算法表现出这种行为,而另一些则没有。请注意,Arrays.sort(...) 是稳定的。
  • @DilumRanatunga 空间经常被用来换取速度。尤其是在 Java 世界中。而且您自己并没有建议任何速度改进 - 比较字符串比您想象的要慢得多。
  • @DilumRanatunga 有一个 Comparator 进行索引字符串比较,每次比较都自动取消装箱从性能的角度来看似乎效率低下。
【解决方案2】:

可能是这样的:

1) 对它们进行排序。

2) 创建空白结果表

3) 从已排序的 Array2 中取出第一个元素,并将其与已排序的 Array1 上第一个元素的原始索引一起放入结果表中

3) 对第二个元素重复步骤 3,依此类推。

计算复杂度就像使用的排序方法:O(nlogn) for quicksort

【讨论】:

    【解决方案3】:

    你绝对可以在 O(n log n) 中做到这一点。但最好的方法取决于什么更重要:快速、干净的代码或不分配额外的内存。

    如果你不关心使用额外的内存,你可以分配一个单独的数组,其中每个元素都是一对:

    public class Pair implements Comparable {
      ...
    }
    

    然后您将使用 Arrays.sort(Object[]) 对数组进行排序。

    如果您不想分配太多空间,可以使用包含Integer 形式的索引的辅助数组:

    final String[] array1 = ...;
    final String[] array2 = ...;
    
    assert array1.length == array2.length;
    
    Comparator<Integer> c = new Comparator<Integer> {
      int compare(Integer a, Integer b) {
        return array1[a].compareTo(array1[b]);
      }
    };
    
    Integer[] aux = new Integer[array1.length];
    for (int i = 0; i < aux.length; ++i) { aux[i] = i; }
    Arrays.sort(aux, c);
    
    String[] result = new String[array1.length];
    for (int i = 0; i < aux.length; ++i) {
      result[i] = array2[aux[i]];
    }
    

    如果您尝试就地完成整个操作并且不分配额外的内存,那么您将需要自己实现其中一种 n-log-n 排序算法...

    【讨论】:

      【解决方案4】:

      (至少)有两种方法可以对一个数组进行排序并重新排序第二个数组,以便对应的元素仍然匹配。两者都需要构造第三个数组并编写自定义比较函数。

      方法一

      定义一个包含每个数组的一个元素的自定义对象。 (在您的情况下,它可能是一个二元素字符串数组。)为自定义对象编写一个比较器(或实现 Comparable),该对象仅比较第一个数组中的元素。从两个输入数组构建自定义对象的数组,对第三个数组进行排序,然后提取结果。

      这是解决此问题最常用的方法。

      方法二

      构造一个初始化为0, 1, 2, ..., n-1(其中n == Array1.length)的整数索引数组。使用比较器对索引数组进行排序,该比较器通过比较它们索引的 Array1 元素来比较索引。

      第二种方法会更快,并且不需要太多的对象构造。

      【讨论】:

        【解决方案5】:

        另外两个想法:

        1. 这些值可以是enum 而不是一组字符串吗?枚举的自然顺序是声明的顺序,所以 Arrays.sort() 可以正常工作。

        2. Guava的Ordering.explicitOrder(List)中存在Helper代码:

          String[] explicitOrder = {"EUROPE", "MIDDLEEAST", "OTHERs", "AUSTRALIA"};
          String[] toSort = ...
          
          Comparator<String> comparator = Ordering.explicit(Arrays.asList(explicitOrder));
          String[] sorted = Arrays.sort(toSort, comparator); 
          

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多