2009-08-21 5 views
30

У меня есть случай, когда использование, если число находится между 0-10 она должна возвращать 0, и если она лежит между 11-20 он должен возвращать 1 и другиеИспользование Java карты для диапазона поиск

0 => 0-3, (0 and 3 are inclusive) 
1 => 4-15, (4 and 15 are inclusive) 
2 => 16-40, (16 and 40 are inclusive) 
3 => 41-88, (41 and 88 are inclusive) 
5 => 89-300 (89 and 300 are inclusive) 

Я думал как я мог бы реализовать и думал Java карт, но это не позволяет диапазон поиска

Я заинтересован в чем-то вроде этого, у меня есть функция

int foo() { 

} 

если Foo возвращает 5, поскольку она лежит между 0 T O 10 Я хотел бы использовать 0, если Foo возвращение 25 он будет использовать 2.

Любые идеи

Edit: На самом деле диапазоны не так просто, как 0-10, 11-20. Я хочу иметь возможность выполнять поиск по диапазону. Прошу прощения за путаницу. Основываясь на запросах, я добавил правильный пример: цифры постоянны.

+0

Просьба реальный пример того, что вы хотите сделать. –

+1

Диапазоны, приведенные в примере, не являются непрерывными. Если вы ищете 4 или 50, вы хотите получить нулевой результат, диапазон выше, ниже или ближе или что? – erickson

+4

@mkal: как вы постоянно меняете требования, вы можете быть менеджером из ада :-) –

ответ

62

Я могу придумать ряд возможных решений для более общей проблемы, когда диапазоны неравномерны и есть «дыры». Самыми простыми являются:

  1. Просто введите карту для всех допустимых значений ключа, с сопоставлением нескольких ключей с тем же значением. Предполагая, что вы используете HashMaps, это должен быть самый эффективный (O (1) поиск), хотя у вас больше времени на настройку, и вы используете больше места.
  2. Используйте навигационную карту и используйте floorEntry(key) для поиска. Это должно быть меньше времени эффективные (O (журнал (N) поиски), но больше пространства эффективно.

Вот решение с использованием NavigableMaps, что позволяет «дырок» в отображении.

private static class Range { 
    public int upper, value; 
    ... 
} 

NavigableMap<Integer, Range> map = new TreeMap<Integer, Range>(); 
map.put(0, new Range(3, 0));  // 0..3  => 0 
map.put(5, new Range(10, 1));  // 5..10 => 1 
map.put(100, new Range(200, 2)); // 100..200 => 2 

// To do a lookup for some value in 'key' 
Map.Entry<Integer,Range> entry = map.floorEntry(key); 
if (entry == null) { 
    // too small 
} else if (key <= entry.getValue().upper) { 
    return entry.getValue().value; 
} else { 
    // too large or in a hole 
} 

На С другой стороны, если нет 'дыры' решение проще:

NavigableMap<Integer, Integer> map = new TreeMap<Integer, Integer>(); 
map.put(0, 0); // 0..4  => 0 
map.put(5, 1); // 5..10 => 1 
map.put(11, 2); // 11..200 => 2 

// To do a lookup for some value in 'key' 
if (key < 0 || key > 200) { 
    // out of range 
} else { 
    return map.floorEntry(key).getValue(); 
} 
+1

Это очень хорошее использование существующей TreeMap для выполните простой поиск диапазона. Обратите внимание, что если есть перекрывающиеся интервалы, то подход вернет этот интервал с ближайшим нижним ключом к клавише поиска. Аналогичным образом, этот подход не поддерживает поиск всех перекрывающихся интервалов, содержащих данный ключ поиска, как описано в http://stackoverflow.com/questions/1580185/data-structure-for-quick-time-interval-look-up – stackoverflowuser2010

+0

Если имеются перекрывающиеся диапазоны, то диапазоны (скорее всего) указаны неправильно. По крайней мере, это мое чтение ЭТОГО вопроса. –

0

Я думаю, что вы хотите что-то вроде строк foo()/10, но это даст вам диапазоны немного от того, что вы просили. Вы всегда можете просто сравнивать с двумя конечными точками для каждого элемента вашей «карты», если они не соответствуют простому шаблону.

3

В более общем случае, который не может быть решён с помощью арифметики, вы можете создать TreeMap с соответствующим компаратором. Добавьте сопоставления для граничных значений, а затем используйте функцию потолочной обработки или floorEntry, чтобы найти соответствующее совпадение.

10

Псевдо-код:

  1. Сохраните границы диапазона в плоском массиве: new int[] {0, 3, 5, 15, 100, 300}.
  2. Двоичный поиск по массиву, как будто вставка числа в массив. См. Arrays.binarySearch().
  3. Если точка ввода ровная, номер не помещается в любой диапазон.
  4. Если точка ввода нечетна, она соответствует соответствующему диапазону. Например, точка ввода для 10 в вышеупомянутой матрице будет 3, размещая ее между 5 и 15, поэтому она принадлежит во втором диапазоне.
+1

Примечание: это работает, только если мы сопоставляем целые числа '{0, 1, 2, ...}'. Для более общих случаев следует использовать карту какого-либо рода. –

0

Я думаю, что самым простым решением было бы добавлять отображения из верхних границ ваших диапазонов в значение, которое соответствует картам, и просто увеличивать ваш номер (ключ на карте) до тех пор, пока вы не достигнете сопоставления (которое - верхняя граница диапазона, в котором находится ваш номер).

Другим способом было бы заполнить карту всеми элементами в диапазоне и добавить отображение для каждого.

Какой является более эффективным, зависит от того, является ли это, вероятно, вы должны запросить все числа в диапазоне многократно (использовать последнее решение), или только некоторые из чисел в несколько раз (используйте первый)

 Смежные вопросы

  • Нет связанных вопросов^_^