Aquecimento: bitvectors aleatórios
Como aquecimento, podemos começar com o caso em que cada vetor de bit é escolhido, de maneira uniforme, aleatoriamente. Acontece que o problema pode ser resolvido no tempo (mais precisamente, o 1.6 pode ser substituído pelo lg 3 ).O(n1.6min(k,lgn))1.6lg3
Consideraremos a seguinte variante de dois conjuntos do problema:
Conjuntos dados de bitvectors, determinar onde existe um par não sobrepostos s ∈ S , t ∈ T .S,T⊆{0,1}ks∈S,t∈T
A técnica básica para resolver isso é dividir e conquistar. Aqui está um algoritmo de tempo usando dividir e conquistar:O(n1.6k)
Divida e T com base na posição do primeiro bit. Em outras palavras, a forma S 0 = { s ∈ S : s 0 = 0 } , S 1 = { s ∈ S : s 0 = 1 } , t 0 = { t ∈ T : t 0 = 0 } , T 1 = { t ∈ T : tSTS0={s∈S:s0=0}S1={s∈S:s0=1}T0={t∈T:t0=0} .T1={t∈T:t0=1}
Agora, procure recursivamente um par sem sobreposição de , de S 0 , T 1 e de T 1 , S 0 . Se qualquer chamada recursiva encontrar um par não sobreposto, produza-o; caso contrário, emita "Não existe um par sobreposto".S0,T0S0,T1T1,S0
Como todos os vetores de bits são escolhidos aleatoriamente, podemos esperar e | T b | ≈ | T | / 2 . Portanto, temos três chamadas recursivas e reduzimos o tamanho do problema em um fator de dois (ambos os conjuntos são reduzidos em tamanho por um fator de dois). Após a divisão de lg min ( | S | , | T | ) , um dos dois conjuntos é reduzido ao tamanho 1 e o problema pode ser resolvido em tempo linear. Temos uma relação de recorrência ao longo das linhas de|Sb|≈|S|/2|Tb|≈|T|/2lgmin(|S|,|T|) , cuja solução é T ( n ) = O ( n 1,6 k ) . Contabilizando o tempo de execução com mais precisão no caso de dois conjuntos, vemos que o tempo de execução é O ( min ( | S | , | T | ) 0,6 max ( | S | , | TT(n)=3T(n/2)+O(nk)T(n)=O(n1.6k) .O ( min ( | S| , | T| )0,6max ( | S| , | T| )K)
Isso pode ser melhorado, observando que, se , a probabilidade de um par não sobreposto existir é exponencialmente pequena. Em particular, se x , y são dois vectores aleatórios, a probabilidade de que eles são não-sobreposição é ( 3 / 4 ) k . Se | S | = | T | = n , existem n 2 pares desse tipo; portanto, por um limite de união, a probabilidade de existir um par não sobreposto é no máximo n 2 ( 3k ≥ 2,5 lgn + 100x , y(3/4)k|S|=|T|=nn2 . Quando k ≥ 2,5 lg n + 100 , este é ≤ 1 / 2 100 . Portanto, como uma etapa de pré-processamento, se k ≥ 2,5 lg n + 100 , podemos retornar imediatamente "Não existe par não sobreposto" (a probabilidade de que isso esteja incorreto é insignificante pequeno), caso contrário, executamos o algoritmo acima.n2(3/4)kk≥2.5lgn+100≤1/2100k≥2.5lgn+100
Assim, alcançamos um tempo de execução de (ou O ( min ( | S | , | T | ) 0,6 max ( | S | , | T | ) min ( k , lg n ) ) para a variante de dois conjuntos proposta acima), para o caso especial em que os vetores de bits são escolhidos uniformemente aleatoriamente.O(n1.6min(k,lgn))O(min(|S|,|T|)0.6max(|S|,|T|)min(k,lgn))
Obviamente, essa não é uma análise do pior caso. Os vetores de bits aleatórios são consideravelmente mais fáceis do que o pior caso - mas vamos tratá-lo como um aquecimento, para obter algumas idéias que talvez possamos aplicar ao caso geral.
Lições do aquecimento
Podemos aprender algumas lições com o aquecimento acima. Primeiro, dividir e conquistar (dividir em uma posição de bit) parece útil. Segundo, você deseja dividir em uma posição de bit com o máximo de nessa posição possível; quanto mais 0 houver, menor será a redução no tamanho do subproblema.10
Em terceiro lugar, isto sugere que o problema fica mais difícil como a densidade de 's fica menor - se há muito poucos 1 é entre os bitvectors (eles são na sua maioria 0 's), os olhares problema muito difícil, já que cada divisão reduz o tamanho dos subproblemas um pouco. Portanto, defina a densidade Δ como a fração de bits que é 1 (ou seja, de todos os n k bits) e a densidade da posição de bit i como a fração de vetor de bits que é 1 na posição i .110Δ1nki1i
Manipulação de densidade muito baixa
Como próximo passo, podemos nos perguntar o que acontece se a densidade for extremamente pequena. Acontece que se a densidade em cada posição de bit for menor que , garantimos a existência de um par não sobreposto: existe um argumento de existência (não construtivo) mostrando que algum par não sobreposto deve existir. Isso não nos ajuda a encontrá-lo, mas pelo menos sabemos que ele existe.1/k−−√
Por que esse é o caso? Digamos que um par de vetores de bits esteja coberto pela posição do bit i se x i = y i = 1 . Observe que todo par de vetores de bits sobrepostos deve ser coberto por alguma posição de bit. Agora, se fixarmos uma posição de bit específica i , o número de pares que podem ser cobertos por essa posição de bit é no máximo ( n Δ ( i ) ) 2 < n 2 / k . Somando todos os kx,yixi=yi=1i(nΔ(i))2<n2/kkdas posições de bits, descobrimos que o número total de pares cobertos por alguma posição de bit é . Isso significa que deve existir algum par que não esteja coberto por nenhuma posição de bit, o que implica que esse par não se sobrepõe. Portanto, se a densidade é suficientemente baixa em todas as posições de bits, certamente existe um par não sobreposto.<n2
No entanto, não consigo identificar um algoritmo rápido para encontrar um par sem sobreposição, nesse regime, mesmo que um esteja garantido. Não vejo imediatamente nenhuma técnica que produza um tempo de execução que tenha uma dependência sub-quadrática de . Portanto, este é um bom caso especial para se concentrar, se você quiser gastar algum tempo pensando sobre esse problema.n
Em direção a um algoritmo de caso geral
No caso geral, uma heurística natural parece ser: escolher a posição de bit com o maior número de 1 's (isto é, com a mais alta densidade), e divisão sobre ele. Em outras palavras:i1
Encontre uma posição de bit que maximize Δ ( i ) .iΔ(i)
Divida e T com base na posição do bit i . Em outras palavras, forma S 0 = { s ∈ S : s i = 0 } , S 1 = { s ∈ S : s i = 1 } , T 0 = { t ∈ T : t i = 0 } , T 1 = { t ∈ T :STiS0={s∈S:si=0}S1={s∈S:si=1}T0={t∈T:ti=0} .T1={t∈T:ti=1}
Agora, procure recursivamente um par sem sobreposição de , de S 0 , T 1 e de T 1 , S 0 . Se qualquer chamada recursiva encontrar um par não sobreposto, produza-o; caso contrário, emita "Não existe um par sobreposto".S0,T0S0,T1T1,S0
O desafio é analisar seu desempenho no pior dos casos.
Vamos supor que, como uma etapa de pré-processamento, primeiro calculemos a densidade de cada posição de bit. Além disso, se para cadai, assuma que a etapa de pré-processamento produz "Um par sobreposto existe" (percebo que isso não exibe um exemplo de par sobreposto, mas vamos deixar isso de lado como um desafio à parte). Tudo isso pode ser feito no tempoO(nk). As informações de densidade podem ser mantidas com eficiência, como fazemos chamadas recursivas; não será o principal contribuinte para o tempo de execução.Δ(i)<1/k−−√iO(nk)
Qual será o tempo de execução deste procedimento? Não tenho certeza, mas aqui estão algumas observações que podem ajudar. Cada nível de recursão reduz o tamanho do problema em cerca de bitvectors (por exemplo, denbitvectors paran-n/ √n/k−−√n bitvectors). Portanto, a recursão só pode ser √n−n/k−−√ níveis profundos. No entanto, não sei imediatamente como contar o número de folhas na árvore de recursão (há muito menos que3 √k−−√ sai), então não tenho certeza a que tempo de execução isso deve levar.3k√