Título:
Dada uma matriz inteira nums
, encontre uma sub-matriz contínua com a maior soma (a sub-matriz contém pelo menos um elemento) e retorne a maior soma.
Exemplos:
Entrada: [ -2 , 1 , -3 , 4 , -1 , 2 , 1 , -5 , 4 ], Saída: 6 Explicação: A soma das sub-matrizes consecutivas [ 4 , -1 , 2 , 1 ] é a maior, que é 6 .
A primeira vez que fiz essa pergunta pela primeira vez, a idéia mais direta é: percorrer toda a matriz, encontrar todas as suas subsequências e depois encontrar a maior. A idéia geral é, naturalmente, usar dois índices i, j e, em seguida, obter o valor da matriz entre i, j e, em seguida, usar o método ring para obter o maior; a complexidade de tempo desse método é o (n ^ 2).
Existe uma maneira melhor? Ou podemos encontrar uma estratégia para que o próximo resultado seja maior que a última vez, para que apenas seja necessário percorrer a matriz uma vez?
Obviamente, essa idéia é: se a soma da sequência atual for negativa, a próxima procurará a posição inicial. Ele não contém mais a posição atual e o número de posições anteriores !
Usamos essa ideia para analisar a matriz de exemplo acima: [-2,1, -3,4, -1,2,1, -5,4],
1 Primeira vez: sequência atual e soma = -2 < 0 ; portanto, não considera mais o número da posição 0 2 Segunda vez: sequência atual e soma = 1 > 0 ; então, o máximo atual e max_sum = 1 ; considere o número da posição 1 3 Na terceira vez: sequência e soma atuais = 1 + -3 = -2 < 0 ; portanto, o número anterior a - 3 não é mais considerado ; 4 na quarta vez: sequência e soma atuais = 4 > 0 ; em seguida, o máximo atual e soma_max = 4 ; a sequência máxima neste momento é 4; 5 a quinta vez: a sequência atual e a soma = 4 + -1 = 3 > 0 ; então o máximo atual e a soma_max = 4 ; a sequência máxima no momento é 4; mas porque a soma> 0Ainda precisamos considerar 4 como o ponto inicial 6 pela sexta vez: a sequência e soma atuais = 4 + -1 + 2 = 5 > 0 ; a sequência máxima atual e sum_max = 5 ; a sequência máxima neste momento [ 4 , -1 , 2 ]; 7 sétimo: = corrente de sequência e SUM 4 + - 1 + 2 + 1 = . 6 > 0 ; e a corrente de sequência máximo = sum_max . 6 ; o caso sequência máxima [ 4 - 1 , 2 , 1 ]; 8 segunda Oito vezes: sequência atual e soma = 4 + -1 + 2+ 1 + -5 = 1 > 0 ; sum_max = 6 ; a sequência máxima no momento [ 4 , -1 , 2 , 1 ]; 9 nono: a sequência atual e a soma = 4 + -1 + 2 + 1 + -5 + 4 = 5 > 0 ; sum_max = 6 , a sequência máxima é 10 [ 4 , -1 , 2 , 1 ]; 11 termina!
Dessa maneira, quando percorremos o array, a maior subsequência é encontrada: a complexidade do tempo visível é O (n);
Alguém pode perguntar aqui: o texto acima está apenas passando do elemento 4 da posição 3 até o fim. Haverá um número começando na posição 3 e indo para uma determinada posição maior que a sequência [4, -1,2,1] iniciando no elemento 4?
Obviamente não, por quê? Como dissemos que, enquanto a sequência atual e <0, descartamos todas as posições anteriores, e a sequência e> 0, mantemos essas posições. Portanto, reservamos a posição a partir de 4. Isso mostra que a soma da sequência é maior que 0; e a partir de 4 é obviamente um subconjunto da sequência que começa em 4, e a soma não pode ser maior que a partir de 4.
Há uma brecha óbvia nas idéias acima: se a soma da sequência atual for negativa, a partir da próxima posição, não conterá mais todas as posições do período atual; obviamente, se todos os elementos da matriz forem negativos. Então não podemos encontrar uma subsequência de soma máxima no final; mas sabemos que, se uma sequência é toda negativa, a subsequência máxima é o maior número negativo entre elas; portanto, devemos considerar o caso de todos os números negativos separadamente.
Então, como consideramos uma matriz negativa? Muito simplesmente, se o maior elemento de uma matriz é negativo, então toda a matriz é negativa. Portanto, podemos fornecer o código completo para encontrar a subsequência máxima:
Solução de 1 classe { 2 public : 3 int maxSubArray (vetor < int > & nums) { 4 int max = 0 , temp = 0 ; 5 int allnegative_max = nums [ 0 ]; 6 para ( int i = 0 ; i <tamanho do número (); i ++ ) { 7 temp + = nums [i]; 8 se (temperatura < 0 ) 9 temperatura = 0 ; 10 if (max <temp) 11 max = temp; 12 if (nums [i]> allnegative_max) 13 allnegative_max = nums [i]; // Usado para determinar se todos são negativos 14 ) 15 if (allnegative_max < 0 ) // Indica que a matriz é toda negativa 16 return allnegative_max; 17 else 18 return max; 19 } 20 };
Obviamente, essa pergunta pode ser mais aprofundada: encontre a posição inicial da maior subsequência da soma? Então, como codificar?
solução de classe { public : int maxSubArray (vetor < int > & nums) { int max = 0 , temp = 0 ; int start1, start2; int allnegative_max = nums [ 0 ]; for ( int i = 0 ; i <tamanho do número (); i ++ ) { temp + = nums [i]; if (temp < 0 ) { temp = 0 ; start1 = i +1 ; } if (max < temp) max = temp; if (nums [i]> allnegative_max) { allnegative_max = nums [i]; // Usado para julgar se todos são números negativos start2 = i; } } if (allnegative_max < 0 ) // A matriz é todos os números negativos return allnegative_max; else return max; } };
Onde start1 e start2 indicam o local