Estrutura de Dados e Algoritmo | Realização da Soma Máxima de Subseqüência


Soma máxima de subsequência

【Título】

给定(可能有负数)整数a(1)、a(2)、……a(n),求 a(1)+a(2)+……+a(j)的最大值。
为方便起见,若所有的整数为负数,则最大子序列和为0.

也就是:在一系列整数中,找出连续的若干个整数,这若干个整数之和 最大。

[Implementação de código]

  • Método 1: Método exaustivo
    • Exaustivamente possível, devido ao loop aninhado de três níveis, tempo de execução O (N ^ 3)
    • Idéia do algoritmo: calcule a soma de cada sub-sequência, ou seja, calcule a soma dos números i-ésésimo-j-ésimo na sequência (j> = i) e compare
  • Versão na linguagem C: o protótipo da função é int maxSubSum (int a []);
#include <stdio.h>

int maxSubSum(int a[]){
	int maxSum = 0;
	int sum, i, j, k;
    int len = sizeof(a) / sizeof(int);
	for(i = 0; i < len; i++){
		for(j = i; j < len; j++){
			sum = 0;
			for(k = i; k <= j; k++){
				sum += a[k];//计算 a[i] 到 a[j] 的和 
			}
			if(sum > maxSum){
				maxSum = sum;
			} 
		}
	}
	return maxSum;
}

int main(){
	int a[] = {-2, 11, -4, 13, -5, -2};
	int max = maxSubSum(a);
	printf("%d\n",max);
	return 0;
}
  • Versão da linguagem C: o protótipo da função é int maxSubSum (int a [], int n);
#include <stdio.h>

int maxSubSum(int a[], int n){
	int maxSum = 0;
	int sum, i, j, k;
	for(i = 0; i < n; i++){
		for(j = i; j < n; j++){
			sum = 0;
			for(k = i; k <= j; k++){
				sum += a[k];//计算 a[i] 到 a[j] 的和 
			}
			if(sum > maxSum){
				maxSum = sum;
			} 
		}
	}
	return maxSum;
}

int main(){
	//int a[] = {-2, 11, -4, 13, -5, -2};
	int a[] = { -2, 4, -3, 5, 7, -1, 8, 1 };
	int len = sizeof(a) / sizeof(int);//有负数所以 strlen(a) 不能用 
	int max = maxSubSum(a, len);
	printf("%d\n",max);	
	return 0;
}
  • Método dois:

    • Simplifique com base no primeiro, remova uma camada do loop for, tempo de execução O (N ^ 2)
    • Idéia do algoritmo: O terceiro loop for do primeiro algoritmo possui muitos cálculos repetitivos desnecessários, como: calcular a soma de ij, mas a soma de ijj-1 foi calculada no loop anterior, sem necessidade Repita o cálculo, para que o loop for possa ser removido
  • Versão em linguagem C

#include <stdio.h>

int maxSubSum(int a[], int n){
	int maxSum = 0;
	int sum, i, j;
	for(i = 0; i < n; i++){
		sum = 0;
		for(j = i; j < n; j++){
			sum += a[j];
			if(sum > maxSum){
				maxSum = sum;
			} 
		}
	}
	return maxSum;
}

int main(){
	//int a[] = {-2, 11, -4, 13, -5, -2};
	int a[] = { -2, 4, -3, 5, 7, -1, 8, 1 };
	int len = sizeof(a) / sizeof(int);//有负数所以 strlen(a) 不能用 
	int max = maxSubSum(a, len);
	printf("%d\n",max);	
	return 0;
}
  • Método 3: Dividir e conquistar
    • Ideia algorítmica: divida o problema em dois subproblemas aproximadamente iguais e depois resolva-os recursivamente.Esta é a parte "dividida". No estágio de "governança", as soluções dos dois subproblemas são corrigidas e algum trabalho adicional pode ser feito e, finalmente, a solução de todo o problema é obtida.
    • Nesse problema, se a sequência for dividida em duas partes do meio, a maior soma de subsequências poderá aparecer em três locais, na metade esquerda dos dados de entrada, na metade direita ou no limite. Os dois primeiros casos podem ser resolvidos recursivamente.A soma máxima do terceiro caso pode ser obtida encontrando a soma máxima da primeira metade (incluindo o último elemento da primeira metade) e a máxima da segunda metade (incluindo o primeiro elemento da segunda metade) O resultado é uma soma e as duas somas são adicionadas no momento.
    • Tempo de execução O (N log N)
  • Versão em linguagem C
#include <stdio.h>

int maxSubSum(int a[], int left, int right){
	// 判断是否只有一个元素
    if (left == right) {
        if (a[left] > 0) {
            return a[left];
        } else {
            return 0;
        }
    }
    int center = (left + right) / 2;
    int maxLeftSum = maxSubSum(a, left, center);
    int maxRightSum = maxSubSum(a, center + 1, right);
    // 左端处理
    int maxLeftBorderSum = 0;
    int leftBorderSum = 0;
    int i;
    for (i = center; i >= left; i--) {
    	leftBorderSum += a[i];
        if (leftBorderSum > maxLeftBorderSum) {
            maxLeftBorderSum = leftBorderSum;
        }
    }

    // 右端处理
    int maxRightBorderSum = 0;
    int rightBorderSum = 0;
    for (i = center + 1; i <= right; i++) {
        rightBorderSum += a[i];
        if (rightBorderSum > maxRightBorderSum) {
            maxRightBorderSum = rightBorderSum;
        }
    }
    // 返回最大值
    int maxBorderSum = maxLeftBorderSum + maxRightBorderSum;
	return maxBorderSum > maxLeftSum ? maxBorderSum > maxRightSum ? maxBorderSum : maxRightSum
				: maxLeftSum > maxRightSum ? maxLeftSum : maxRightSum;
}

int main(){
	//int a[] = {-2, 11, -4, 13, -5, -2};
	int a[] = { -2, 4, -3, 5, 7, -1, 8, 1 };
	int max = maxSubSum(a, 0, sizeof(a) / sizeof(int) - 1);
	printf("%d\n",max);
	return 0;
}
  • Método 4: ponto de partida ideal, método de digitalização

    • Idéia do algoritmo: suponha que [i] seja o ponto de partida da maior sequência; se [i] for negativo, não poderá representar o ponto de partida da sequência ideal, porque qualquer subsequência que contenha um [i] como ponto de partida É aprimorado usando um [i + 1] como ponto de partida.
    • Da mesma forma, qualquer subsequência negativa não pode ser o prefixo da subsequência ideal.
    • Tempo de execução: O (N)
  • Versão em linguagem C

#include <stdio.h>

int maxSubSum(int a[], int n){
	int maxSum = 0;
	int sum = a[0], i;
	/*考虑如果全是负数,那么返回最大的负数,
	如果最后的和为正,那么就使用扫描法*/
	for(i = 1; i < n; i++){
		if(sum < 0){//当前数小于0,换为下一个数
			sum = a[i];
		}else{
			sum += a[i];
		}
		if(sum > maxSum){
			maxSum = sum;
		}
	}
	return maxSum;
}

int main(){
	//int a[] = {-2, 11, -4, 13, -5, -2};
	int a[] = { -2, 4, -3, 5, 7, -1, 8, 1 };
	int len = sizeof(a) / sizeof(int);//有负数所以 strlen(a) 不能用 
	int max = maxSubSum(a, len);
	printf("%d\n",max);	
	return 0;
}
Publicado 120 artigos originais · elogiado 201 · 230.000 visualizações +

Acho que você gosta

Origin blog.csdn.net/wugenqiang/article/details/105467380
Recomendado
Clasificación