Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 16.08.2017, 11:47
Аспирант
Отправить личное сообщение для HJ90 Посмотреть профиль Найти все сообщения от HJ90
 
Регистрация: 24.07.2012
Сообщений: 37

Быстрый поиск интервалов в массиве
Всем привет!
Подскажите пожалуйста быстрый, по возможности не сложный, алгоритм решения такой задачи.

У меня есть отсортированный большой массив с интервалами "beg" и "end".
И есть некий отрезок, например: [30, 60].
Нужно найти все пересечения этого отрезка с интервалами в массиве.

Самое простое это линейный поиск:
var intervals = [
	{beg: 8,   end: 16}, 
	{beg: 24,  end: 32}, 
	{beg: 40,  end: 48}, 
	{beg: 56,  end: 64}, 
	{beg: 72,  end: 80}, 
	{beg: 88,  end: 96}
];

var range = [30, 60];
var overlap = [];

for(i = 0; i < intervals.length; i++)
{
	var A = intervals[i].beg;
	var B = intervals[i].end;
	
	if(range[0] <= B && range[1] >= A)
	{
		overlap.push( intervals[i] );
	}
}
console.log(overlap);
Все работает, и в результате мы получим массив интервалов с которым полностью или частично пересекается наш диапазон:
{beg: 24, end: 32}
{beg: 40, end: 48}
{beg: 56, end: 64}
Но в этой реализации слишком много лишних итераций.

Первое что пришло в голову по оптимизации это бинарный поиск первого левого пересечения и добивка линейным поиском.
И тут проблема.
Я могу найти элемент в массиве "intervals" только если есть точное совпадение например "beg" с началом отрезка.
А как найти элемент между двумя значениями не могу придумать.
Ответить с цитированием
  #2 (permalink)  
Старый 16.08.2017, 12:01
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,109

HJ90,
буду приятно удивлён, если кто-то предложит лучше вариант, чем у вас.
Ответить с цитированием
  #3 (permalink)  
Старый 16.08.2017, 12:27
Аспирант
Отправить личное сообщение для HJ90 Посмотреть профиль Найти все сообщения от HJ90
 
Регистрация: 24.07.2012
Сообщений: 37

Сообщение от рони Посмотреть сообщение
HJ90,
буду приятно удивлён, если кто-то предложит лучше вариант, чем у вас.
Спасибо за ответ!
Лучше может быть оптимизация линейного поиска.
Например прерывать цикл, если слева мы непрерывно что-то нашли, а после этого уже нет перекрытия - тогда искать до конца массива уже нет смысла.

Но это незначительная оптимизация. Прирост производительности будет только если искомие элементы находятся вначале массива.
Ответить с цитированием
  #4 (permalink)  
Старый 16.08.2017, 13:00
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 25.10.2016
Сообщений: 1,012

Разумеется, тут можно применить поиск делением пополам. Если отрезки массива не пересекаются между собой, то всё довольно просто.
Ответить с цитированием
  #5 (permalink)  
Старый 16.08.2017, 13:17
Аспирант
Отправить личное сообщение для HJ90 Посмотреть профиль Найти все сообщения от HJ90
 
Регистрация: 24.07.2012
Сообщений: 37

Alexandroppolus, а можете хотя бы в двух словах описать как бинарным поиском найти элемент в котором есть диапазон значений от 40 до 48?

Отрезки не пересекаются между собой. Но вот че-то я туплю уже второй день.

Например если за основу взять такую функцию бинарного поиска, то мы найдем элемент с индексом 2:
var intervals = [
	{beg: 8,   end: 16}, 
	{beg: 24,  end: 32}, 
	{beg: 40,  end: 48}, 
	{beg: 56,  end: 64}, 
	{beg: 72,  end: 80}, 
	{beg: 88,  end: 96}
];

function bin_search(arr, val)
{
	var min = 0;
	var max = arr.length - 1; 
	
	while (min < max)                
	{	
		var mid = Math.floor((min + max) / 2);
		
		if(arr[mid].beg < val) {min = mid + 1}
		
		else max = mid;
	}
	if(arr[min].beg == val)
	{
		return {index:min};
	}
	return -1;
}
console.log( bin_search(intervals, 40) );
Ответить с цитированием
  #6 (permalink)  
Старый 16.08.2017, 13:44
Аватар для ksa
ksa ksa на форуме
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,215

Сообщение от Alexandroppolus
тут можно применить поиск делением пополам
Хорошая идея.
Сообщение от HJ90
а можете хотя бы в двух словах описать
Ведь у тебя массив отсортирован...

Предложу такой вариант.
- Берем элемент "посередине" массива.
- Узнаем как его "положение" корелирует с нашим отрезком. Т.е. мы ниже, выше, или внутри предполагаемого подмассива.
- Если внутри, значит идем ниже, пока есть пересечение. А потом выше, пока не кончится пересечение.
- Если ниже, делим нижнюю часть пополам и опять проверяем наше местоположение.
- Если выше, делим верхнюю часть пополам и опять проверяем наше местоположение.

Но это довольно сложный алгоритм и смысл в нем есть если массив тот реально здоровенный! А отрезок мал...
Ответить с цитированием
  #7 (permalink)  
Старый 16.08.2017, 13:52
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,791

HJ90,
А массив данных, который присутствует в коде от балды заполнен или это действительно используемые данные?
Ответить с цитированием
  #8 (permalink)  
Старый 16.08.2017, 14:01
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,990

Сообщение от ksa
Если внутри, значит идем ниже, пока есть пересечение. А потом выше, пока не кончится пересечение.
Тогда сразу двигаться вниз и вверх.
Ответить с цитированием
  #9 (permalink)  
Старый 16.08.2017, 14:04
Аспирант
Отправить личное сообщение для HJ90 Посмотреть профиль Найти все сообщения от HJ90
 
Регистрация: 24.07.2012
Сообщений: 37

ksa, спасибо за Ваше предложение! Буду пробовать реализовывать.
Nexus, массив заполнен от балды. А в реале значения какие угодно могут быть, всегда по возрастанию и не пересекаются.
Ответить с цитированием
  #10 (permalink)  
Старый 16.08.2017, 14:06
Аватар для ksa
ksa ksa на форуме
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,215

Сообщение от laimas
Тогда сразу двигаться вниз и вверх.
Это уже как тебе угодно...
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Поиск слова в массиве killex Javascript под браузер 11 14.12.2014 02:37
Поиск объектов в массиве Lynatik Общие вопросы Javascript 24 22.06.2013 12:43
Поиск в массиве, частичное совпадение фонарик Общие вопросы Javascript 25 04.04.2013 07:43
Ajax - быстрый поиск Antant AJAX и COMET 0 01.11.2010 17:18
Поиск в массиве через JavaScript Noran Общие вопросы Javascript 0 10.08.2008 17:31