Создайте карту в Java, которая случайным образом принимает карты. [Закрыто]

1

Я хочу иметь Map в форме:

0 -> 1
2 -> 0
1 -> 2

Или

0 -> 4
1 -> 0
2 -> 2
3 -> 3
4 -> 1

Предполагается, что каждый int будет отображаться точно в отдельный int в диапазоне. Я хочу передать функцию int размером карты и вернуть объект Map. Какой хороший способ реализовать эту функциональность?

  • 1
    сделайте массив 0 .. N, затем перемешайте его, затем поместите в Map порядок от 0 до N. Хорошо, если размер известен с самого начала.
  • 1
    The most efficient way to implement this functionality would be to not use Java. Почему это ?
Показать ещё 3 комментария
Теги:
random
map

4 ответа

2
Лучший ответ
public static Map<Integer,Integer> bijectiveMap(int n) {
        List<Integer> values = new ArrayList<>(n);
        for (int i=0 ; i<n ; i++)
            values.add(i);
        Collections.shuffle(values);

        Map<Integer,Integer> result = new HashMap<>();
        for (int i=0 ; i<n ; i++)
            result.put(i,values.get(i));
        return result;
    }

Выход для n = 10:

{0=7, 1=5, 2=3, 3=6, 4=1, 5=4, 6=2, 7=8, 8=9, 9=0}

1

Может произойти тасовка. Возможно, это не самый быстрый, но, безусловно, самый чистый способ.

public Map<Integer, Integer> getRandomMapping(int min, int max){
    List<Integer> arr = new ArrayList<Integer>();
    //Fill array in order
    for(int i = 0; i < max + 1; i++){
        arr.add(i + min);
    }
    //Shuffle
    Collections.shuffle(arr);

    //Read into map
    Map<Integer, Integer> m = new HashMap<Integer, Integer>();
    for(int i = 0; i < max + 1; i++){
        m.put(new Integer(i + min), arr.get(i));
    }

    return m;
}
1

Забудьте о Map. Просто перетасуйте Array ArrayList (инициализированный с a[i] = i). Качество распределения зависит от вашего алгоритма тасования.

  • 0
    +1, с массивом / ArrayList работать проще. Если по какой-то причине действительно необходимо вернуть Map , вы можете создать класс, который оборачивает массив и реализует интерфейс Map .
0

Если избегайте Collections.shuffle. Вот

public static Map<Integer, Integer> foo(final int size) {
    final Map<Integer, Integer> out = new HashMap<Integer, Integer>(size*5);
    final List<Integer> values = new ArrayList<Integer>(size);
    Random r = new Random();
    for (int i = 0; i < size; i++) {
        values.add(i, i);
    }
    for (int i = size; i > 0; i--) {
        out.put(new Integer(i), values.remove(r.nextInt(i)));
    }
    return out;
}
  1. Создайте все коллекции соответствующего размера (коэффициент загрузки hashmap здесь составляет около 20%, он будет потреблять слишком много места).
  2. Перемешать и добавить элементы в один цикл
  3. Поскольку keySet не заказывается, нет необходимости переходить от 1 до N
  4. Положите Random как переходный статический, тогда в некоторых случаях он будет быстрее.
  5. Использовать коллекции Apache для int и long, а не для Integer wrapper

    final static transient Random r = new Random();
    final public static Map<Integer, Integer> foo(final int size) {
        final Map<Integer, Integer> out = new HashMap<Integer, Integer>(size*5);
        final List<Integer> values = new ArrayList<Integer>(size);
        int i;
    
        for (i = 0; i < size; i++) {
            values.add(i, i);
        }
        for (; i > 0; i--) {
            out.put(new Integer(i), values.remove(r.nextInt(i)));
        }
        return out;
    }
    

Я прошу прощения за циклы List, это было слишком много std :: vector на сегодняшний день. Быстрое решение

final static transient Random rand = new Random();
final public static Map<Integer, Integer> foo(final int size) {
    final Map<Integer, Integer> out = new HashMap<Integer, Integer>(size*5);
    final Integer[] values = new Integer[size];
    int i, r;
    for (i = 0; i <size; i++) {
        values[i] = i;
    }
    for (; i > 0; i--) {
        r = rand.nextInt(i);
        out.put(i, values[r]);
        values[r] = values[i-1];
    }
    return out;
}
  • 1
    Ваша реализация, размер = 100_000: 1557 мс, размер = 1_000_000: 167130 мс. Внедрение с использованием Collections.shuffle, размер = 100_000: 95 мс, размер = 1_000_000: 2934 мс. Гораздо быстрее, ты сказал? Удаление элементов values имеет ужасную стоимость, тогда как Collections.shuffle меняет только элементы. Так или иначе !
  • 0
    Вопрос решен, я не хочу начинать дискуссию. Все, что я хочу сказать, это то, что удаление элемента в ArrayList - это O (n), поэтому последний цикл - это O (n ^ 2), тогда как Collections.shuffle - это O (n). Период. Попробуйте сами! pastebin.com/Se7CugK4
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню