【アルゴリズム】最大サブ配列
7148 ワード
問題の説明:
理解:
暴力の解:
JAvaコード実装:
分治解:
上記のアルゴリズムの漸進時間の複雑さはΘ(nlg(n)).JAvaコード実装:
問題の規模を縮小:
問題の規模を縮小する方法:
JAvaコードは次のとおりです.
参考文章:https://www.cnblogs.com/SyBlog/p/11371922.html#commentform参考書:『アルゴリズム導論』
, 。
理解:
, , 。 , : , , 。 , , , 。
暴力の解:
( ) , ( ) C(2,n), , Θ(n2)。 A (A 1 n),A.length A , ; :
BRUTE_FORCE(A)
i = 1
sum = -infinity
for i <= A.length, inc by 1
j = i
last_sum = 0
for j <= A.length, inc by 1
last_sum += A[j]
if last_sum > sum
sum = last_sum
start = i
end = j
return (start, end, sum)
JAvaコード実装:
private static void bruteForce(int[] arr) {
int start = -1, end = -1, max = 0;
for (int i = 0; i < arr.length; i++) {
// lastSum ,
int lastSum = 0;
for (int j = i; j < arr.length; j++) {
lastSum += arr[j];
if (lastSum > max) {
max = lastSum;
start = i;
end = j;
}
}
}
System.out.println("maxSum = " + max + ", start : " + start + ", end = " + end);
}
分治解:
: , , 。 : , A[1...n] left[1...mid] right[mid+1...n], mid=(1+n)/2 , , , , , 。
left/right , , O(n), Θ(n2)。 A[mid] A[mid+1] , Θ(n2) 。 , left/right , A[mid] A[mid+1] ; , 。
, O(n) 。 :
(1) :
FIND_CROSSING_MAX_SUBARRAY(A, low, mid, high)
left_sum = -infinity
sum = 0
i = mid
for i >= low, dec by 1
sum += A[i]
if sum > left_sum
left_sum = sum
left_index = i
right_sum = -infinity
sum = 0
i = mid + 1
for i <= high, inc by 1
sum += A[i]
if sum > right_sum
right_sum = sum
right_index = i
return (left_index, right_index, left_sum+right_sum)
(2) :
FIND_MAX_SUBARRAY(A, low, high)
if low == high
return (low, high, A[low])
else
mid = down_trunc((low + high) / 2)
(left_start, left_end, left_sum) =
FIND_MAX_SUBARRAY(A, low, mid)
(right_start, right_end, right_sum) =
FIND_MAX_SUBARRAY(A, mid+1, high)
(cross_start, cross_end, cross_sum) =
FIND_CROSSING_MAX_SUBARRAY(A, low, mid, high)
if left_sum > right_sum and left_sum > cross_sum
return (left_start, left_end, left_sum)
else if right_sum > left_sum and right_sum > cross_sum
return (right_start, right_end, right_sum)
else
return (cross_start, cross_end, cross_sum)
上記のアルゴリズムの漸進時間の複雑さはΘ(nlg(n)).JAvaコード実装:
private static int[] findMaxSubArray(int[] arr, int left, int right) {
//
if (left == right) {
return new int[]{left, right, arr[left]};
}
int mid = (left + right) / 2;
int[] leftResult = findMaxSubArray(arr, left, mid);
int[] rightResult = findMaxSubArray(arr, mid + 1, right);
int[] crossingResult = findCrossingMaxSubArray(arr, mid, left, right);
if (leftResult[2] > rightResult[2] && leftResult[2] > crossingResult[2]) {
return leftResult;
} else if (rightResult[2] > leftResult[2] && rightResult[2] > crossingResult[2]) {
return rightResult;
} else {
return crossingResult;
}
}
private static int[] findCrossingMaxSubArray(int[] arr, int mid, int left, int right) {
int leftIndex = -1, rightIndex = -1, leftMax = Integer.MIN_VALUE, rightMax = Integer.MIN_VALUE, sum = 0;
for (int i = mid; i >= left; i--) {
sum += arr[i];
if (sum > leftMax) {
leftIndex = i;
leftMax = sum;
}
}
sum = 0;
for (int i = mid + 1; i <= right; i++) {
sum += arr[i];
if (sum > rightMax) {
rightIndex = i;
rightMax = sum;
}
}
return new int[]{leftIndex, rightIndex, leftMax + rightMax};
}
問題の規模を縮小:
問題の規模を縮小する方法:
, , , ? , , , , , 。 :
1. : 、
2. ,
3. ,
1 。
A[1] A[i] (1<=i<=n), A[i] , A[1]+...+A[i-1]>=0。 i<=2 , 2 。
i>2 , A[1]...A[i] , : A[1] 、 A[i] A[1] A[i] ;
A[i] , A[1] A[i] , , , 0, 2 。 2 。
3, A[i] , A[i]<0。 A[i] , A[j] (1<=j1 ,A[j]+...+A[i] , A[1]+...+A[j-1] 0 A[1]+...+A[i] 。 , A[i] A[i] 。
, Θ(n)。 , , 。
LINEAR_SEARCH_MAX_SUBARRAY(A)
sum = -infinity
start = 0
end = 0
cur_sum = 0
cur_start_index = 1
i = 1
for i <= A.length, inc by 1
cur_sum += A[i]
if cur_sum < 0
cur_sum = 0
cur_start_index = i + 1
else
if sum < cur_sum
sum = cur_sum
start = cur_start_index
end = i
return (start, end, sum)
JAvaコードは次のとおりです.
private static int[] linerSearchMaxSubArray(int[] nums) {
int start = 0;
int end = 0;
int max = 0;
int temp = 0;
int ts = 0;
for (int i = 0; i < nums.length; i++) {
temp += nums[i];
if (temp < 0) {
ts = i + 1;
temp = 0;
} else {
if (temp > max) {
start = ts;
end = i;
max = temp;
}
}
}
return new int[]{start, end, max};
}
参考文章:https://www.cnblogs.com/SyBlog/p/11371922.html#commentform参考書:『アルゴリズム導論』