データ構造とアルゴリズム|最大サブシーケンス合計の実現


最大サブシーケンス合計

【タイトル】

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

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

【コード実装】

  • 方法1:徹底的な方法
    • ネストされた3レベルのforループ、実行時間O(N ^ 3)により、すべてが可能な限り
    • アルゴリズムのアイデア:各サブシーケンスの合計を計算します。つまり、シーケンス内のi番目からj番目の数の合計を計算し(j> = i)、比較します。
  • C言語バージョン:関数プロトタイプは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;
}
  • C言語バージョン:関数プロトタイプは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;
}
  • 方法2:

    • 最初のものに基づいて簡略化し、forループの1つの層を削除し、実行時間O(N ^ 2)
    • アルゴリズムのアイデア:最初のアルゴリズムの3番目のforループには、iからjまでの合計の計算など、不要な反復計算がたくさんありますが、iからj-1までの合計は前のループで計算されているため、必要ありません。計算を繰り返して、forループを削除できるようにします
  • 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;
}
  • 方法3:分割して征服する
    • アルゴリズムのアイデア:問題を2つのほぼ等しいサブ問題に分割し、それらを再帰的に解決するこれは「分割された」部分です。「ガバナンス」の段階では、2つのサブ問題のソリューションにパッチが適用され、いくつかの追加作業が実行され、最終的に問題全体のソリューションが取得されます。
    • この問題では、シーケンスを中央から2つの部分に分割すると、最大のサブシーケンスの合計が、入力データの左半分、右半分、または境界を越えた3か所に表示される可能性があります。最初の2つのケースは再帰的に解決できます。3番目のケースの最大合計は、前半の最大合計(前半の最後の要素を含む)と後半の最大合計(後半の最初の要素を含む)を見つけることで取得できます。結果は合計であり、この時点で2つの合計が加算されます。
    • 実行時間O(NログN)
  • 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;
}
  • 方法4:最適な開始点、スキャン方法

    • アルゴリズムのアイデア:[i]が最大のシーケンスの開始点であるとすると、[i]が負の場合、最適なシーケンスの開始点を表すことができません。 [i + 1]を開始点として使用することで改善されます。
    • 同様に、負のサブシーケンスを最適なサブシーケンスのプレフィックスにすることはできません。
    • 実行時間:O(N)
  • 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;
}
120件の元の記事を公開 201 件を賞賛 230,000回の閲覧+

おすすめ

転載: blog.csdn.net/wugenqiang/article/details/105467380