[알고리즘 가이드 노트] 최대 연속 서열과
3492 단어 算法导论笔记
1. 나누어 다스리는 귀속 해법
세 가지 상황으로 나뉘어
키 코드
/* , , mid */
int findMaxCrossingSubArray(int * A, int low, int mid, int high)
{
int leftIndex = mid;
int rightIndex = mid;
int leftSum = 0;
int rightSum = 0;
int leftFinalSum = A[mid];
int rightFinalSum = 0;
for (int i = mid; i >= 0; i--)
{
leftSum += A[i];
if (leftSum > leftFinalSum)
{
leftIndex = i;
leftFinalSum = leftSum;
}
}
for (int i = mid + 1; i < high; i++)
{
rightSum += A[i];
if (rightSum > rightFinalSum)
{
rightIndex = i;
rightFinalSum = rightSum;
}
}
return leftFinalSum + rightFinalSum;
}
int findMaximumSubarray(int *A, int low, int high)
{
if (low == high)
{
return A[low];
}
// mid
int mid = (high + low) / 2;
int left = findMaximumSubarray(A, low, mid);
int right = findMaximumSubarray(A, mid + 1, high);
int cross = findMaxCrossingSubArray(A, low, mid, high);
return max(max(left, right), cross);
}
2. 수학적 사고방식
만약 앞에서 더하기를 마이너스로 한다면 나는 더하지 않겠다고 선택하고, 정수라면 나는 가입할 것이다. 최종적으로 매번 가입할 때마다 이전의 결과와 비교하여 큰 값을 가지고 돌아와야 한다!intfindMaximumSubarray2(int*A, intsize) 참조;
키 코드
int findMaximumSubarray2(int *A, int size)
{
int sum = 0;
int result = A[0];
for (int i = 0; i < size; i++)
{
if (sum < 0)
{
sum = 0;
}
sum += A[i];
result = result > sum ? result : sum;
}
return result;
}
3. 요약
방법2의 시간 복잡도가 비교적 낮고 방법2는 인위적으로 분석과 취사를 했고 알고리즘을 정진하여 문제를 간단하게 만들었다.배우고 생각하지 않으면 망한다. 컴퓨터의 기술을 배운 후에 수학의 사고까지 더하면 왕왕 적은 노력으로 큰 효과를 거둔다!
전체 테스트 인증 코드:
#include "pch.h"
#include
#define max(a, b) a > b ? a : b
int findMaxCrossingSubArray(int * A, int low, int mid, int high);
int findMaximumSubarray(int *A, int low, int high);
int findMaximumSubarray2(int *A, int size);
int main()
{
int a[] = { 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7 };
std::cout << findMaximumSubarray(a, 0, 15) << std::endl;
std::cout << findMaximumSubarray2(a, sizeof(a) / sizeof(a[0])) << std::endl;
return 0;
}
/* , , mid */
int findMaxCrossingSubArray(int * A, int low, int mid, int high)
{
int leftIndex = mid;
int rightIndex = mid;
int leftSum = 0;
int rightSum = 0;
int leftFinalSum = A[mid];
int rightFinalSum = 0;
for (int i = mid; i >= 0; i--)
{
leftSum += A[i];
if (leftSum > leftFinalSum)
{
leftIndex = i;
leftFinalSum = leftSum;
}
}
for (int i = mid + 1; i < high; i++)
{
rightSum += A[i];
if (rightSum > rightFinalSum)
{
rightIndex = i;
rightFinalSum = rightSum;
}
}
return leftFinalSum + rightFinalSum;
}
int findMaximumSubarray(int *A, int low, int high)
{
if (low == high)
{
return A[low];
}
// mid
int mid = (high + low) / 2;
int left = findMaximumSubarray(A, low, mid);
int right = findMaximumSubarray(A, mid + 1, high);
int cross = findMaxCrossingSubArray(A, low, mid, high);
return max(max(left, right), cross);
}
int findMaximumSubarray2(int *A, int size)
{
int sum = 0;
int result = A[0];
for (int i = 0; i < size; i++)
{
if (sum < 0)
{
sum = 0;
}
sum += A[i];
result = result > sum ? result : sum;
}
return result;
}