从渐进列表中选择非重复随机数

时间:2014-06-10 15:08:00

标签: java

这是我的例子 - 选择1-20的随机数,然后是2-21,3-22,依此类推 不包括之前的选秀权。我是Java新手,做错了。

import java.util.Random;
import java.util.ArrayList;
import java.util.List;

public class RandomGenerator {

      static int temp;
    public static void main(String[] args) {

        List<Integer> randomNumberArray = new ArrayList<Integer>(); 

        Random RandomNumber = new Random();

    for (int i = 0; i<=20; i++)
    {
        temp = RandomNumber.nextInt(i+20) +1+i;
        if (!randomNumberArray.contains(temp))
        {
            {
                randomNumberArray.add(temp);
            }

        }

        System.out.println(randomNumberArray);
    }    

4 个答案:

答案 0 :(得分:0)

您不能排除之前的选秀权。这样的东西会打印20个随机数(例如1-20的所有随机数)。

public static void main(String[] args) {
  java.util.Set<Integer> picked = new TreeSet<Integer>();
  Random rand = new Random();
  while (picked.size() < 20) {
    int temp = 1+rand.nextInt(20);
    if (picked.contains(temp)) {
      continue;
    }
    picked.add(temp);
    System.out.println(temp);
  }
}

我不确定我是否理解你的&#34;踩踏&#34;想法,但为temp添加此内容,它也会这样做 -

int temp = 1+picked.size()+rand.nextInt(20+picked.size());

答案 1 :(得分:0)

有几件事要讨论。

1)如果您的号码看到有重复,那么它将跳过它并继续下一个号码,例如,如果您运行5次并且它找到重复一次,那么结果列表中的数字将只有4个数字不是5!,因为它跳过了一个。 (不确定这是否是你想要的)

2)您随机生成的数字不会像您期望的那样增长。 例如:在循环的第六次迭代中,随机数将生成为:

RandomNumber.nextInt(25) +6;

这意味着数字范围不是6-26而是 6-30!

因为:nextInt将在0到24之间返回一个int,然后再向该int添加6个。

编辑:

要解决您的第一个问题,您可以继续生成数字,直到您为for循环的单个循环生成一个不重复的数字。

为此,您可以使用 do-while 循环,以便在检查for循环中的数字是否重复之前至少执行一次数字生成。

因此,您可以从

调整for循环
for (int i = 0; i<=20; i++)
{
    temp = RandomNumber.nextInt(20) +1+i;
    if (!randomNumberArray.contains(temp))
    {
        {
            randomNumberArray.add(temp);
        }

    }

    System.out.println(randomNumberArray);
}

<强>到

for (int i = 0; i<=20; i++)
{
    do {
        temp = RandomNumber.nextInt(20) +1+i;
    } while (randomNumberArray.contains(temp));

    randomNumberArray.add(temp);

    System.out.println(randomNumberArray);
}

请注意,while表达式中的check是相反(没有感叹号)之前for循环中if表达式中的内容,因为我们do想要继续生成新的随机数while我们的数字是重复的。

由于我们仍然在for循环的一个循环内循环,因此它将始终生成具有适当值i的数字,该值已为循环设置。

答案 2 :(得分:0)

这里的诀窍是使用Collections.shuffle(List list)

    List<Integer> list = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
    Collections.shuffle(list);
    System.out.println(list);

渐进版本是这样的:

    // Wrap it in an ArrayList so I can modify it.
    List<Integer> list = new ArrayList(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20));
    for (int i = 21; i < 25; i++) {
        System.out.println(list);
        // Shuffle it.
        Collections.shuffle(list);
        // Grab one.
        Integer take = list.get(0);
        list.remove(take);
        System.out.println("Took " + take);
        // Add my new candidate.
        list.add(i);
    }

或者你可以全力以赴,使它成为Iterable

public static class CreepingRandom implements Iterable<Integer> {

    // The starting list.
    private final List<Integer> start;
    // How many steps to add.
    private final int steps;
    // What int to start adding.
    private final int from;

    public CreepingRandom(int initialSize, int from, int steps) {
        // Make my start list.
        start = new ArrayList<Integer>(initialSize);
        // Fill it.
        for (int i = 1; i <= initialSize; i++) {
            start.add(i);
        }
        // Remember where to start from.
        this.from = from;
        // Remember how many steps.
        this.steps = steps;
    }

    @Override
    public Iterator<Integer> iterator() {
        return new CreepingIterator();
    }

    private class CreepingIterator implements Iterator<Integer> {

        // Track how many I've delivered.
        int delivered = 0;
        // The next number to add.
        int add = from;
        // My current list.
        final ArrayList<Integer> list = new ArrayList(start);

        @Override
        public boolean hasNext() {
            return delivered < steps;
        }

        @Override
        public Integer next() {
            // Shuffle it.
            Collections.shuffle(list);
            // Pull one out.
            Integer next = list.get(0);
            // Add my new one in.
            list.set(0, add++);
            // Count them.
            delivered += 1;
            return next;
        }

    }

}

public void test() {
    for (Integer i : new CreepingRandom(20, 21, 100)) {
        System.out.println(i);
    }
}

    private class CreepingIterator implements Iterator<Integer> {

        // Track how many I've delivered.
        int delivered = 0;
        // The next number to add.
        int add = from;
        // My current list.
        final ArrayList<Integer> list;

        CreepingIterator() {
            // Copy the start list - Use LinkedList for efficiency of add and removeFirst.
            list = new ArrayList(start);
        }

        @Override
        public boolean hasNext() {
            return delivered < steps;
        }

        @Override
        public Integer next() {
            // Shuffle it.
            Collections.shuffle(list);
            // Pull one out.
            Integer next = list.get(0);
            // Add my new one in.
            list.set(0, add++);
            // Count them.
            delivered += 1;
            return next;
        }

    }

}

public void test() {
    for (Integer i : new CreepingRandom(20, 21, 100)) {
        System.out.println(i);
    }
}

答案 3 :(得分:0)

由于允许元素的范围不是太大,您还可以保留所有可能数字的池并选择其中一个。你可以用例如来自this answer的RandomSet。

import java.util.*;
import java.lang.*;

/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
    static class RandomSet<E> extends AbstractSet<E> {

        List<E> dta = new ArrayList<E>();
        Map<E, Integer> idx = new HashMap<E, Integer>();

        public RandomSet() {
        }

        public RandomSet(Collection<E> items) {
            for (E item : items) {
                idx.put(item, dta.size());
                dta.add(item);
            }
        }

        @Override
        public boolean add(E item) {
            if (idx.containsKey(item)) {
                return false;
            }
            idx.put(item, dta.size());
            dta.add(item);
            return true;
        }

        /**
         * Override element at position <code>id</code> with last element.
         * @param id
         */
        public E removeAt(int id) {
            if (id >= dta.size()) {
                return null;
            }
            E res = dta.get(id);
            idx.remove(res);
            E last = dta.remove(dta.size() - 1);
            // skip filling the hole if last is removed
            if (id < dta.size()) {
                idx.put(last, id);
                dta.set(id, last);
            }
            return res;
        }

        @Override
        public boolean remove(Object item) {
            @SuppressWarnings(value = "element-type-mismatch")
            Integer id = idx.get(item);
            if (id == null) {
                return false;
            }
            removeAt(id);
            return true;
        }

        public E get(int i) {
            return dta.get(i);
        }

        public E pollRandom(Random rnd) {
            if (dta.isEmpty()) {
                return null;
            }
            int id = rnd.nextInt(dta.size());
            return removeAt(id);
        }

        @Override
        public int size() {
            return dta.size();
        }

        @Override
        public Iterator<E> iterator() {
            return dta.iterator();
        }
    }
    public static void main (String[] args) throws java.lang.Exception
    {
        RandomSet<Integer> rs = new RandomSet<Integer>();
        for (int i = 0; i < 20; ++i) {
            rs.add(i);
        }

        int count = 50;

        Random r = new Random();

        for (int i = 0; i < count; i++) {
            System.out.println(rs.pollRandom(r));
            rs.remove(i);
            rs.add(i + 20);
        }
    }
}

使用智能结构时,总体时间复杂度为O(N + K),其中N是请求的民意调查数,K是池的大小。

运行Ideone示例:http://ideone.com/Sfltr7