最大のサブシリーズの合計
今日、私は他の人のブログで最大の連続サブシーケンスについて多くを学びました。私は好きな2つのアルゴリズムを繰り返すことに焦点を当てます。
1
配列sum [i]を使用して、最初からi番目までの数値の合計を表し、sum [j] -sum [i-1]を使用して、i番目からi番目までの数値の合計を表します。 j番目のシーケンス、最も内側のループを削除、C言語コードは次のとおりです。
#include <stdio.h>
//N是数组长度,num是待计算的数组,sum是数组前缀和,放在全局区是因为可以开很大的数组
int N, num[16384], sum[16384];
int main()
{
//输入数据
scanf("%d", &N);
for(int i = 1; i <= N; i++)
scanf("%d", &num[i]);
//计算数组前缀和
sum[0] = 0;
for(int i = 1; i <= N; i++) {
sum[i] = num[i] + sum[i - 1];
}
int ans = num[1]; //ans保存最大子数列和,初始化为num[1]能保证最终结果正确
//i和j分别是枚举的子数列的起点和终点
for(int i = 1; i <= N; i++) {
for(int j = i; j <= N; j++) {
int s = sum[j] - sum[i - 1];
if(s > ans) ans = s;
}
}
printf("%d\n", ans);
return 0;
}
ブロガーの意味によると、それを少し最適化することもできます。合計要素グループの代わりに、num配列を使用して合計を直接保存します。
#include <stdio.h>
int N, num[16384];
int main() {
//输入数据
scanf("%d", &N);
for(int i = 1; i <= N; i++) {
scanf("%d", &num[i]);//计算数组前缀和
num[i] = num[i] + num[i - 1];
}
int ans = num[1]; //ans保存最大子数列和,初始化为num[1]能保证最终结果正确
//i和j分别是枚举的子数列的起点和终点
for(int i = 1; i <= N; i++) {
for(int j = i; j <= N; j++) {
int s = num[j] - num[i - 1];
if(s > ans) ans = s;
}
}
printf("%d\n", ans);
return 0;
}
2
分割統治法、つまり、関数の再帰呼び出しを使用してこの問題を解決します。
関数を使用して、中心位置を分割点として配列を2つの部分に分割します。答えは、次の3つのケースに分けることができます
。1。最大サブ番号は左側にリストされています
2.右側に
3.分割統を越えて、左側と右側のそれぞれが一部を占めています。
1つまたは2つの場合は、3番目のケースが発生するまで繰り返すことができます。
3番目のケースに対処し
ます:1。分割点を開始点として使用して、左側と右側の最大値を見つけ(開始点が決定されているため、複雑さは高くありません)、それらを追加します。
アイデアは非常に明確です。次に、どの状況で十分かを判断するだけです。これは問題ではありません。再帰呼び出しを引き続き使用して、1、2の最大のサブシーケンスを見つけて、分割点の左側と右側の最大値。
int solve(int left,int right,int *num) {
//左值,右值,数组地址
if(left==right) {
//递归结束
return num[right];
}
int mid=right+left>>1;
int lans =solve (right,mid,num);//Left Answer,即left max
int rans = solve (mid+1,left,num);//Right Answer
int sum = 0, lmax = num[mid], rmax = num[mid + 1];
for(int i = mid; i >= left; i--) {
sum += num[i];
if(sum > lmax) lmax = sum;
}
sum = 0;
for(int i = mid + 1; i <= right; i++) {
sum += num[i];
if(sum > rmax) rmax = sum;
}
//答案是三种情况的最大值
int ans = lmax + rmax;
if(lans > ans) ans = lans;
if(rans > ans) ans = rans;
return ans;
}