如何最好地比较Java整数集?

时间:2014-07-18 14:18:27

标签: java list integer set duplicates

在学习Java的同时,我正在使用许多彩票来提高我的新技能。作为练习,我想为给定的随机种子创建所有13.9M 6球组合。我已经设法为给定的种子生成线条,但我目前没有检查它们是否是唯一的,因此我得到重复。

我想知道他采取什么方法来检查每个生成的行与先前生成的行?我目前正在使用一个集合来保存每行中的6个数字,并且想知道我是否应该比较集合或者是否应该使用列表或其他内容?

所有建议表示赞赏: - )

3 个答案:

答案 0 :(得分:0)

您可以使用containsAll()方法。有一些方法可以生成独特的组合,而不是比较一切。请分享一些代码。

Set<Integer> nums = new HashSet<Integer>(Arrays.asList(new Integer[] {1, 2, 3, 4, 5}));
Set<Integer> nums2 = new HashSet<Integer>(Arrays.asList(new Integer[] {1, 2, 6, 4, 5}));
System.out.println(nums.containsAll(nums2));

答案 1 :(得分:0)

有了这些数字,我建议将每一行添加到一个Set(如HashSet)。现在,如果您有自己的类来表示这些行,那么您将不得不重写该类中的equals和hashcode方法。但是一旦你完成了这个,在每次添加到Set之后,你可以看到Set的大小是否随着Set.size()的增加而增加。如果没有,那就是重复。这样,用于检查重复的算法与任何其他解决方案相比实际上要少一个数量级。

答案 2 :(得分:0)

(在彩票上读一下6个数字在1到49之间选择,数字不能重复两次)

如果您希望确保组合是唯一的,确保它没有被使用,然后才能执行类似的操作

Set<Set<Integer>> previousCombinations = new HashSet<Set<Integer>>();
...
Set<Integer> newCombination = new HashSet<Integer>(Arrays.asList(22, 10, 1, 14, 45, 14));
if (!previousCombinations.add(newCombination)) {
    // its a duplicate
} else {
    // its not a duplicate
}

然而,另一个不需要检查以前生成的组合的解决方案如下:

这将生成彩票号码的随机组合,这些彩票号码保证是唯一的,直到所有可能的组合都用完为止,而不必检查所有先前随机生成的组合。请注意,乐透号码按升序排序,以使其更加真实,您可以随机播放它们。

这可以通过

使用

1)一个自定义随机数生成器,如果您继续调用getNextValue()方法而不重复,则会以随机顺序生成自定义范围的所有唯一编号,直到返回所有数字为止(之后循环) )

2)一种算法,给出0到组合总数之间的数字,并返回与该数字对应的实际组合。例如,在我们的例子中,0对应于[0,1,2,3,4,5],而13983815对应于[43,44,45,46,47,48]

  public static void main(String[] args) throws Throwable {
    for (int i = 0; i < 1000000; i++) {
      System.out.println(Arrays.toString(getRandomLottoNumbers()));
    }
  }

  private static final RandomFunction lottoFunction = new RandomFunction(choose(49,
      6));

  public static int[] getRandomLottoNumbers() {
    int[] combination = mthCombination(lottoFunction.getNextValue(), 49, 6);
    for (int i = 0; i < combination.length; i++) {
        combination[i]++;
    }
  }

  // Based on http://en.wikipedia.org/wiki/Linear_congruential_generator
  public static final class RandomFunction {

    private final long a;

    private final long c;

    private final long m;

    private int curr = 0;

    public RandomFunction(int period) {
      m = period;
      List<Integer> primes = primeFactors(period);
      Set<Integer> uniquePrimes = new HashSet<Integer>(primes);

      long aMinusOne = 1;
      if (primes.size() >= 2 && primes.get(0) == 2 && primes.get(1) == 2) {
        aMinusOne = 2;
      }

      for (Integer prime : uniquePrimes) {
        aMinusOne *= prime;
      }

      // make 'a' random
      int rand = (int) (1 + (1000 * Math.random()));

      a = (aMinusOne * rand) + 1;

      int potentialC = 0;
      while (potentialC <= 1) {
        potentialC = 2 + (int) (period * Math.random());

        for (Integer prime : uniquePrimes) {
          while (potentialC % prime == 0) {
            potentialC /= prime;
          }
        }
      }
      c = potentialC;
      curr = (int) (period * Math.random());
    }

    public int getNextValue() {
      curr = (int) ((a * curr + c) % m);
      return curr;
    }
  }

  // Based on http://www.codeguru.com/cpp/cpp/algorithms/general/article.php/c16255/Linear-Search-based-algorithm-for-Mth-Lexicographic-ordering-of-Mathematical-Permutation-and-Combina.htm
  public static int[] mthCombination(int m, int n, int k) {
    if (k == 0) {
      return new int[0];
    }
    if (k == n) {
      int[] result = new int[k];
      for (int i = result.length - 1; i >= 0; i--) {
        result[i] = --k;
      }
      return result;
    }
    int subChoose = choose(n - 1, k - 1);
    if (m < subChoose) {
      int[] subResult = mthCombination(m, n - 1, k - 1);
      int[] result = new int[subResult.length + 1];
      for (int i = 0; i < subResult.length; i++) {
        result[i + 1] = subResult[i] + 1;
      }
      return result;
    } else {
      int[] result = mthCombination(m - subChoose, n - 1, k);
      for (int i = 0; i < result.length; i++) {
        result[i]++;
      }
      return result;
    }
  }

  public static int choose(int n, int k) {
    if (k < 0 || k > n) {
      return 0;
    }
    if (k > n / 2) {
      k = n - k;
    }

    long denominator = 1;
    long numerator = 1;
    for (int i = 1; i <= k; i++) {
      denominator *= i;
      numerator *= (n + 1 - i);
    }
    return (int) (numerator / denominator);
  }

  public static List<Integer> primeFactors(int number) {
    List<Integer> primeFactors = new ArrayList<Integer>();
    if (number < 1) {    
      return primeFactors;
    }

    while (number % 2 == 0) {
      primeFactors.add(2);
      number /= 2;
    }
    for (int i = 2; i * i <= number; i += 2) {
      while (number % i == 0) {
        primeFactors.add(i);
        number /= i;
      }
    }
    if (number != 1) {
      primeFactors.add(number);
    }

    return primeFactors;
  }