2016-10-31 7 views
1

У меня есть массив/dict (HashMap) положительных целых чисел. мне нужно найти количество пар, которые имеют абсолютное различие больше или равно заданному числу, К.Найти число пар с разницей больше или равным заданному числу

import random 
import time 

#given number 
k = 4 

# List of 2,00,000 random numbers in range 0-1000 
strength = [random.randrange(0,1000) for x in range(200000)] 
strength.sort() 

# start clock 
start1 = time.clock() 

n = len(strength) 

# count keeps track of number of pairs found 
count = 0 

for x in range(n): 
    for y in range(x,n): 

     if abs(strength[x] - strength[y]) >= k: 
      # if found, all number from this point to the end will satisfy 
      count += n-y 
      # So no need to go to the end 
      break 

end1 = time.clock() 
print(count) 
print(end1-start1) 

Все ответы я нахожу предназначены для пар меньше или равно заданному числу.

Мне нужно найти количество пар, которые имеют абсолютное различие больше или равно заданному числу, К.

+0

Что вы хотите сказать? – hatchet

+0

@hatchet отредактировал вопрос – Moulick

ответ

0

Обратите внимание, что общее число пар n * (n - 1)/2, так что если вы можете найти количество пар с разницей меньше, чем K, число пар с разницей больше, чем K просто n * (n - 1)/2 - num_pairs_with_diff_less_than_K

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

+0

Это еще одна проблема, которую я имею, я не могу найти решение, которое включает только пары, строго меньшие, чем K, все, что я нахожу или умею кодировать, также содержит равный случай. – Moulick

0

Вы можете получить комбинацию из 2 элементов массива, а затем фильтровать/уменьшать их в соответствии с разницей.

Можно выполнить эту работу на JavaScript следующим образом;

Array.prototype.combinations = function(n){ 
 
    return this.reduce((p,c,i,a) => p.concat(n > 1 ? a.slice(i+1).combinations(n-1).map(e => (e.push(c),e)) 
 
               : [[c]]),[]); 
 
}; 
 

 
function getAcordingToDiff(a,d){ 
 
    return a.combinations(2) 
 
      .reduce((p,c) => Math.abs(c[0]-c[1]) >= d ? (p.push(c),p) : p ,[]); 
 
} 
 

 
var arr = Array(30).fill().map((_,i) => i+1); // array from [1,...,30] 
 
console.log(JSON.stringify(arr)) 
 
console.log(JSON.stringify(getAcordingToDiff(arr,25))); // diff >= 25

Объяснение:

Таким образом, в центре кода выше, очевидно, лежит функция Array.prototype.combinations. Для тех, кто не знаком с JS, это просто обычная функция, которую мы определяем в прототипе объекта Array (так что теперь у каждого массива есть доступ к этой функции, например, arr.combinations(n)). Но давайте использовать более выразительный язык и реорганизовать вышеупомянутый набор комбинаций метод в общую функцию.

function combinations(a,n){ 
    var sa; 
    return a.reduce(function(p,c,i,a){ 
        if (n > 1) sa = combinations(a.slice(i+1), n-1).map(e => (e.push(c),e)); 
        else sa = [[c]]; 
        return p.concat(sa); 
        },[]); 
} 

Так как вы заметите combinations(a,n) рекурсивная функция, которая принимает массив a и число пунктов n. Он работает на основе сохранения первого элемента входного массива и рекурсивного вызова самого себя с помощью одного элемента более короткого массива, combinations(a.slice(i+1), n-1), и с одним меньшим количеством элементов подсчитывается до n уменьшается до 1, и в этом случае он начинает цикл возврата с тем, что осталось от входной массив и каждый элемент обернут в массив, sa = [[c]].

Итак, в цикле возврата рекурсивных вызовов мы берем результирующий массив и нажимаем сохраненный первый элемент (помним -> Он работает на основе сохранения первого элемента входного массива) в каждый элемент возвращаемого массива (помните -> ... и каждый элемент обернут в массив, sa = [[c]]).

Так вот оно ... Вы должны уметь выяснить подробности.

Однако в нашем приложении нам задан массив чисел, и мы попросили получить только 2 комбинации товаров с определенной разницей. В этом конкретном случае нам не нужно вычислять все комбинации, а затем фильтровать их. Мы можем сделать это на пути построения наших комбинаций.По мере увеличения требуемой величины разности d это приведет к огромному усилению по сравнению с методом фильтрации, так как теперь, когда d становится больше, мы устраняем все больше и больше двух комбинаций элементов, даже до их создания. И ... давайте прочно связать наш код с работой только с двумя элементами и слить все в одну функцию. Ниже приведены результаты работы;

function getCombosWithDiff(a, d, n = 2){ 
 
    var sa; 
 
    return a.reduce(function(p,c,i,a){ 
 
        if (n > 1) sa = getCombosWithDiff(a.slice(i+1), d, n-1).reduce((r,e) => Math.abs(e[0]-c) > d ? (e.push(c),r.push(e),r) 
 
                               : r, []); 
 
        else sa = [[c]]; 
 
        return p.concat(sa); 
 
        },[]); 
 
} 
 

 
var arr = Array(100).fill().map((_,i) => i+1); 
 
result = getCombosWithDiff(arr,89); 
 
console.log(JSON.stringify(arr)); 
 
console.log(JSON.stringify(result));

Так вот это. Я попробовал приведенный выше код, чтобы перечислить комбинации из двух элементов, каждый из которых имеет разницу больше 10 из массива из 1000 элементов. Он занимает около 5000 мс в Chrome и 14000 мсек в FF. Однако, как упоминалось выше, чем больше значение разности d становится больше, тем короче оно требуется. например, тот же массив с diff 900 будет разрешен всего за 1100 мкс с помощью Chrome и 4000 мсек с FF.

Вы можете проверить и играть here

+0

@redus Можете ли вы рассказать мне, что вы сделали на более удобном языке, потому что я не знаю JS, и мне нужно закодировать это в python ... – Moulick

+0

@duh Вы должны иметь возможность получить две комбинации элементов из сначала входной массив. Я уверен, что в Python есть много примеров. Тогда все, что вам нужно сделать, это уменьшить/отфильтровать те с разницей, которая больше или равна заданному значению 'd'. Я объясню функцию комбинаций несколько часов спустя, потому что теперь я покидаю офис. – Redu

+0

@redus уверен, не спешите. Вы хотите сказать, что сделать все возможные комбинации элементов из массива? а затем проверить, превышает ли разность между двумя числами заданное значение d? – Moulick

0

Создать 1001-элементный массив A целых чисел инициализируется в нулях. Генерируйте ваши случайные целые числа и увеличивайте соответствующий индекс на 1 для каждого такого целого числа. С некоторой математикой вы могли бы сделать это без генерации 2 000 000 случайных целых чисел, но это не стоит сложности.

Создать второе целочисленное 1001-элементное целое B s.t. B [i] = A [0] + ... + A [i]

Ответ представляет собой сумму от i = 0 до 1000-k от B [i] * (2 000 000 - B [i + k-1])