测试长度为n的未排序整数列表是否表示集合{1,...,n}

时间:2016-03-01 18:57:18

标签: java algorithm

现在我有以下解决方案,我认为这个解决方案相当清楚。

import java.util.Arrays;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

public class ConsecutiveNumbers {
  public static void main(String[] args) {
    List<Integer> good = Arrays.asList(2, 1);
    System.out.println(is1ToN(good)); // true

    List<Integer> bad1 = Arrays.asList(3, 1);
    System.out.println(is1ToN(bad1)); // false

    List<Integer> bad2 = Arrays.asList(1, 1, 2);
    System.out.println(is1ToN(bad2)); // false
  }

  public static boolean is1ToN(List<Integer> numbers) {
    SortedSet<Integer> set = new TreeSet<>(numbers);
    return set.isEmpty() || (set.size() == numbers.size() && set.first() == 1
        && set.last() == set.size());
  }
}

是否有更好(更有效或更清晰)的解决方案?

2 个答案:

答案 0 :(得分:5)

创建一个大小为N的布尔数组。通过列表迭代,依次考虑列表中每个元素的值,v。如果v超出范围1 ... n,则返回false。如果p [v-1]为true,则表示您具有重复值,因此答案为false。否则,将p [v-1]设置为true。如果到达列表的末尾,则返回true。

使用BitSet而不是数组可能会或者可能不值得。这将节省一些内存,尽管所需的额外内存仍为O(N)。但它会增加CPU工作量。交易是否值得,取决于用例。

答案 1 :(得分:2)

根据我的评论,实施可能是:

public static boolean is1ToN(List<Integer> numbers) {
  Set<Integer> set = new HashSet<>(numbers);
  if (set.size() != numbers.size()) {
    return false;
  }
  for (int i = 1; i < numbers.size() + 1; i++) {
    if (!set.contains(i)) {
      return false;
    }
  }
  return true;
}