【问题标题】:What's the name and time complexity of this sorting algo?这个排序算法的名称和时间复杂度是多少?
【发布时间】:2015-10-24 21:57:21
【问题描述】:

所以我有一个对象列表。都是同一类型。让我们称之为Foo。 Foo 有一个属性“值”,我想按该值排序。 我已经用 Java 实现了该算法。它是通用的,我提供了两个示例。一种使用整数,另一种使用枚举常量作为值的类型。

算法简单地迭代所有可能的值,然后为每个这样的值迭代输入列表。具有相同值的所有元素都将添加到结果列表中。就是这样。

如果有 11 个值,那么它将迭代列表 11 次。所以时间复杂度是 O(11*n)。但是 11 是一个常数,所以它确实是 O(n),这对于排序算法来说非常好。即使可能有数十亿个值,它仍然是 O(n)。这个假设正确吗?

我实际上在我必须处理的一些代码中发现了类似的东西。我花了一些时间才弄清楚代码确实如此,因为我不希望任何人无缘无故地实际实现排序算法。代码是由不知道 Java 允许您按Collections.sort(myList, Comparator.comparing(Foo::getValue)) 排序的人编写的。

起初我认为这是一种对列表进行排序的可怕方式,但后来我意识到它实际上非常快,甚至稳定。但它不是到位。我想知道那个算法的名字是什么。

在实际数据上进行测试时,常见算法(例如快速排序)的性能可能仍然要好得多。所以我想知道这个是否曾经使用过。

代码如下:

import java.util.*;
import java.util.function.Function;
import java.util.stream.*;

public class SortAlgo {
  /**
   * Sorts a list. The sort is stable. 
   * The input won't be changed. A new list is returned instead.
   * 
   * @param list
   *          The list to be sorted.
   * @param values
   *          The possible values of the field used for the sorting.
   * @param get
   *          A function to get the value.
   * @return A new, sorted list.
   */
  public static <T, V> List<T> sort(final List<T> list, final List<V> values,
      final Function<T, V> get) {
    final List<T> result = new ArrayList<>(list.size());
    for (final V v : values)
      for (final T t : list)
        if (get.apply(t) == v)
          result.add(t);
    assert result.size() == list.size();
    return result;
  }

  static class Foo1 {
    public static final int MIN_VALUE = 0;
    public static final int MAX_VALUE = 10;
    final private int value;

    public Foo1(final int value) {
      this.value = value;
    }

    public int getValue() {
      return this.value;
    }

    @Override
    public String toString() {
      return Integer.toString(this.value);
    }
  }

  static class Foo2 {
    public static enum Value {
      A, B, C, D, E;
    }

    final private Value value;

    public Foo2(final Value value) {
      this.value = value;
    }

    public Value getValue() {
      return this.value;
    }

    @Override
    public String toString() {
      return this.value.name();
    }
  }

  public static void main(final String[] args) {
    final List<Foo1> list1 = new ArrayList<>();
    final Random rng = new Random();
    for (int i = 0; i < 100; i++)
      list1.add(new Foo1(rng.nextInt(Foo1.MAX_VALUE + 1)));

    final List<Integer> values1 = IntStream.rangeClosed(Foo1.MIN_VALUE, Foo1.MAX_VALUE).boxed()
        .collect(Collectors.toList());
    final List<Foo1> sorted1 = sort(list1, values1, Foo1::getValue);

    System.out.println(sorted1);

    // -------------------------

    final List<Foo2> list2 = new ArrayList<>();
    final Foo2.Value[] enums = Foo2.Value.values();
    for (int i = 0; i < 100; i++)
      list2.add(new Foo2(enums[rng.nextInt(enums.length)]));

    final List<Foo2.Value> values2 = Arrays.asList(enums);
    final List<Foo2> sorted2 = sort(list2, values2, Foo2::getValue);

    System.out.println(sorted2);

  }

}

【问题讨论】:

  • 提示一下:在您计算复杂度时,n 是什么?
  • 这是提示还是问题? n 是列表的大小。这是输入的大小。也许将m 用于可能值的数量也是正确的。那么复杂度是O(n*m)?
  • 是的,这正是重点! :)
  • 所以如果m &lt; log n 那么这比O(n log n) 更好。对?几乎总是这样。但是有一个最坏的情况是m==n =&gt; O(nm) == O(n^2)。最好的情况是O(n)。这个算法没有名字吗?

标签: algorithm sorting time-complexity


【解决方案1】:

它本质上是一个counting sort,它是O(n),但是有一个额外的循环,而不是将值存储在一个数组中并且只循环一次。

【讨论】:

  • 但是这个算法没有计数。
  • 假设您首先要查找所有 1。您可以只计算它们,然后在最后输出该数量的 1。您只是在遇到它们时将它们写出来,但效果是一样的。
猜你喜欢
  • 1970-01-01
  • 2015-06-12
  • 1970-01-01
  • 2020-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多