Tempo de cálculo, derivação de complexidade de tempo e análise de algoritmo clássico de dividir e conquistar

Dividir e conquistar é uma ideia para resolver problemas complexos, podendo dividir um problema em vários pequenos problemas e obter a solução do problema original mesclando esses problemas. Este artigo analisa a complexidade do método de dividir e conquistar, e analisa a complexidade de tempo de vários algoritmos específicos por este método.

1 Análise de Complexidade de Dividir e Conquistar

Dividir e conquistar pode ser de tamanho nO problema de n é dividido em kkk escalasnm \frac {n}{m}mnsubproblemas a resolver. Definir o limite de decomposição n 0 = 1 n_0=1n0=1 , e leva 1 unidade de tempo para resolver um problema de tamanho 1 com o algoritmo para resolver o menor subproblema. Vamos decompor o problema original emkkk subproblemas ekkA solução de k subproblemas é combinada na solução do problema original usandof ( n ) f(n)f ( n ) unidades de tempo. comT (n) T(n)T ( n ) significa que a escala de solução do método de dividir e conquistar énnO tempo de cálculo necessário para o problema n é:
T ( n ) = { O ( 1 ) n = 1 k T ( nm ) + f ( n ) n > 1 T(n)=\begin{cases} O( 1) &n=1\\ kT(\frac{n}{m})+f(n)&n>1\\ \end{casos}T ( n )={ O ( 1 )k T (mn)+f ( n )n=1n>1
T ( n ) = nlogmk + ∑ j = 0 logm ( n ) − 1 kjf ( nmj ) (1.1) T(n)=n^{log_m k}+\sum_{j=0}^{log_m(n) -1}k^jf(\frac{n}{m^j})\tag{1.1}T ( n )=nl o gmk+j = 0l o gm( n ) 1kj f(mjn)( 1.1 )
"Introduction to Algorithms" usa uma árvore recursiva no processo de derivação da fórmula (1.1), aqui tentamos usar outro método para deduzir:
quandon > 1 n>1n>1 °, T ( n ) = k T ( nm ) + f ( n ) , T(n)=kT(\frac{n}{m})+f(n),T ( n )=k T (mn)+f ( n ) ,
sejan = mtn=m^tn=mt , 令G ( t ) = T ( mt ) = T ( n ) G(t)=T(m^t)=T(n)G ( t )=T ( mt )=T ( n ) , então
T ( mt ) = k T ( mt − 1 ) + f ( mt ) G ( t ) = k G ( t − 1 ) + f ( mt ) = k ( k G ( t − 2 ) + f ( mt − 1 ) ) + f ( mt ) = k 2 G ( t − 2 ) + kf ( mt − 1 ) + f ( mt ) = ⋯ = kt G ( 0 ) + kt − 1 f ( m ) + kt − 2 f ( m 2 ) + ⋯ + kf ( mt − 1 ) + f ( mt ) = kt G ( 0 ) + ∑ j = 0 t − 1 kjf ( mt − j ) = klogmn + ∑ j = 0 logm ( n ) − 1 kjf ( nmj ) = nlogmk + ∑ j = 0 logm ( n ) − 1 kjf ( nmj ) \begin{split} T(m^t)&=kT(m^{t-1})+f(m^t )\\ G(t)&=kG(t-1)+f(m^t)\\ &=k(kG(t-2)+f(m^{t-1}))+f(m ^t)\\ &=k^2G(t-2)+kf(m^{t-1})+f(m^t)\\ &=\cdots\\ &=k^tG(0)+ k^{t-1}f(m)+k^{t-2}f(m^2)+\cdots+kf(m^{t-1})+f(m^t)\\ &= k^tG(0)+\sum_{j=0}^{t-1}k^jf(m^{tj})\\ &=k^{log_mn}+\sum_{j=0}^{log_m (n)-1}k^jf(\frac{n}{m^j})\\ &=n^{log_mk}+\sum_{j=0}^{log_m(n)-1}k^jf (\frac{n}{m^j})\\ \end{split}T ( mt )G ( t )=k T ( mt 1 )+f ( mt )=k G ( t1 )+f ( mt )=k ( k G ( t2 )+f ( mt 1 ))+f ( mt )=k2 G(t2 )+k f ( mt 1 )+f ( mt )==kt G(0)+kt 1 f(m)+kt 2 f(m2 )++k f ( mt 1 )+f ( mt )=kt G(0)+j = 0t - 1kj f(mt j )=kl o gmn+j = 0l o gm( n ) 1kj f(mjn)=nl o gmk+j = 0l o gm( n ) 1kj f(mjn)
Assim, obtém-se a fórmula (1.1): T ( n ) = nlogmk + ∑ j = 0 logm ( n ) − 1 kjf ( nmj ) T(n)=n^{log_mk}+\sum_{j=0}^{ log_m(n)-1}k^jf(\frac{n}{m^j})T ( n )=nl o gmk+j = 0l o gm( n ) 1kj f(mjn)
Ao calcular a complexidade de tempo, você pode usar diretamenten , m , kn,m,kn ,m ,K é substituído na fórmula para resolver.

2 Análise de Algoritmo Clássico

2.1 Pesquisa binária

A pesquisa binária está em uma sequência ordenada a [ 0 : n ] a [0: n]um [ 0:n ] para encontrar um elemento específicoxxO método de x retorna a posição do elemento na sequência se for encontrado e retorna uma falha de pesquisa se o elemento não estiver na sequência. Tomando como exemplo a sequência ascendente, na busca, cada vez que o elemento encontrado forxxx e o elemento do meio da sequênciamid midmid d para comparação, sex == midx==midx==mid d , retorna a posição; sex < mid x<midx<mid mid , indicando que o elemento que você procura pode estar emmid midNa frente de mid , logo antes dea [ 0 : mid ] a [0: mid]um [ 0:mid d ] continue a procurar da mesma forma; sex > mid x>midx>mid mid , indicando que o elemento que você procura pode estar emmid midDepois do meio , logo depois deum [meio:n] a[meio:n]a [ mi d:n ] para continuar a busca da mesma forma. O código (linguagem C) é o seguinte:

int binary_search(int a[], int num, int low, int high)
//a:要查找的序列,num:要查找的数,low:查找序列的第一个元素,high:查找序列的最后一个元素
{
    
    
	int mid = 0;
	while (low <= high) 
	{
    
    
		mid = (low + high) / 2;
		if (num == a[mid]) return mid;
		else if (num < a[mid]) high = mid - 1;
		else low = mid + 1;
	}
	return -1;
}

O problema de busca binária será 1 de tamanho nnO problema de n é dividido em 1 tamanhon 2 \frac{n}{2}2nO subproblema do problema, o custo de dividir o problema vem da comparação de números, e no final não há necessidade de mesclar, então basta uma ordem constante de tempo para decompor um problema e fundi-lo em um só problema, ou seja, f (n) = cf(n)= cf ( n )=c , pela fórmula (1.1), podemos saber que o tempo necessário para a busca binária é
T ( n ) = nlog 2 1 + ∑ j = 0 log 2 ( n ) − 1 c = 1 + clog 2 n \begin{split } T(n) &=n^{log_21}+\sum_{j=0}^{log_2(n)-1}c\\ &=1+clog_2n \end{split}T ( n )=nl o g21+j = 0l o g2( n ) 1c=1+c l o g2n
Então a complexidade de tempo da busca binária é O ( log 2 n ) O(log_2n)O ( l o g2n ) .

2.2 Classificação por mesclagem bidirecional

No processo de classificação de mesclagem bidirecional, uma sequência não ordenada a [baixa, alta] a[baixa, alta]a [ baixo , _ _hi g h ] será dividido em duas sequências do mesmo tamanhoa [ baixo , médio ] a [ baixo, médio]a [ baixo , _ _mi d ] ,a [ médio + 1 , alto ] a [ médio + 1, alto]a [ mi d+1 ,hi g h ] e, em seguida, classifique as duas sequências separadamente. Após a conclusão da classificação, as duas sequências são classificadas separadamente e a classificação pode ser concluída mesclando as duas sequências. O código da linguagem C é o seguinte:

void merge(int a[], int tmp[], int low, int mid, int high)
//合并算法,a[low,mid]有序,a[mid+1,high]有序,merge函数使得a[low,high]有序
{
    
    
	int i, j, k;
	for (i = low; i <= high; i++) tmp[i] = a[i];
	//将a[low,high]复制到tmp[low,high]中
	i = low, j = mid+1, k = low;
	//i,j用来指示数组tmp中的位置,k用来指示数组a中的位置
	while (i <= mid && j <= high)
	{
    
    
		if (tmp[i] <= tmp[j])
		//从tmp的两个有序段中挑出最小的元素放入a的下一个位置
		{
    
    
			a[k] = tmp[i];
			i++;
		}
		else
		{
    
    
			a[k] = tmp[j];
			j++;
		}
		k++;
	}
	while (i <= mid) //tmp[mid+1,high]已经在a中,将tmp[low,mid]中的剩余元素填入a
	{
    
    
		a[k] = tmp[i];
		i++, k++;
	}
	while (j <= high) //tmp[low,mid]已经在a中,将tmp[mid+1,high]中的剩余元素填入a
	{
    
    
		a[k] = tmp[j];
		j++, k++;
	}
}


void merge_sort(int a[], int tmp[], int low, int high)
//归并排序算法,a:要排序的数组,tmp:相同长度的辅助数组,low:排序序列的第一个元素,high:排序序列的最后一个元素
{
    
    
	int mid = 0, i;
	if (low < high)
	{
    
    
		mid = (low + high) / 2;
		merge_sort(a, tmp, low, mid);
		merge_sort(a, tmp, mid + 1, high);
		//将排序问题分成两个规模减半的子问题
		merge(a, tmp, low, mid, high);
		//将子问题的结果合并
	}
}

O algoritmo de classificação por mesclagem bidirecional terá um tamanho de nnO problema de n é dividido em 2 escalasn 2 \frac{n}{2}2nsubproblema. O problema de divisão é implementado por meio de chamadas de função e o problema de mesclagem gasta principalmente tempo no array aaa e a matriztmp tmpt m p transferem elementos entre si, entãof ( n ) = nf(n)=nf ( n )=n , da fórmula (1.1), pode-se saber que o tempo necessário para a ordenação de mesclagem bidirecional é:
T ( n ) = nlog 2 2 + ∑ j = 0 log 2 ( n ) − 1 2 jn 2 j = n + nlog 2 n \begin{ split} T(n)&=n^{log_22}+\sum_{j=0}^{log_2(n)-1}2^j\frac{n}{2^j} \\ &=n+nlog_2n \end{split}T ( n )=nl o g22+j = 0l o g2( n ) 12j2jn=n+n l o g2n
Então a complexidade de tempo da ordenação de mesclagem bidirecional é O ( nlog 2 n ) O(nlog_2n)O ( n l o g2n ) .

Acho que você gosta

Origin blog.csdn.net/diqiudq/article/details/128589092
Recomendado
Clasificación