C语言求子数组相加的和最大,C语言强化(三)求子数组的最大和

上一篇解答了在栈里面求最小值元素的问题,这一篇,来聊聊怎么找到数组中子数组的最大和。

通过这道题,你可以掌握

如何根据用户输入创建数组

如何在一连串数字中找到和最大的某一段连续数字子串

如何发现问题的潜在规律并利用这个规律设计算法,解决问题

0818b9ca8b590ca3270a3433284dd417.png

思路

连续数相加要最大,说明左右两边的数肯定不是负数,否则不可能最大

连续数序列中允许存在负数,前提是负数前面的一段正数相加要大于这个负数,否则两者抵消后,和会变小

算法

遍历数组

遇到正数,

不断累加,遇到的第一个正数要记录下标

遇到负数,

记录下标,把此下标减1和之前记录的正数的下标之间的数组作为一个可能最大数组,

与之前的可能最大数组比较,若变大,则取代!

判断累加的值与负数大小关系

如果累加值大于负数,则继续累加

如果累加值小于等于负数,舍弃此负数,向前移动,累加值清零

源代码

#include

#include

#include

#include

#include

using namespace std;

/**

输入一个整形数组,数组里有正数也有负数。

数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。

求所有子数组的和的最大值。要求时间复杂度为 O(n)。

例如输入的数组为 1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为 3, 10, -4, 7, 2,

因此输出为该子数组的和 18。

思路

连续数相加要最大,说明左右两边的数肯定不是负数

连续数序列中允许存在负数,前提是负数前面的一段正数相加要大于这个负数

算法:

遍历数组

遇到正数,不断累加,遇到的第一个正数要记录下标

遇到负数,记录下标,

把此下标减1和之前记录的正数的下标之间的数组作为一个可能最大数组,

与之前的可能最大数组比较,若变大,则取代!

判断累加的值与负数大小关系

如果累加值大于负数,则继续累加

如果累加值小于等于负数,舍弃此负数,向前移动,累加值清零

*/

void main()

{

//根据用户输入创建数组

vector oriArray;

int n=0,count=0;

string str;

bool endFlag=true;

while(endFlag){

cout<

cin>>str;

if(str=="e"){

endFlag=false;

}else{

stringstream(str)>> n;

oriArray.push_back(n);

count++;

}

}

cout<

for(int i =0;i

cout<

}

//求最大子数组

/**

add:累加值

ori:累加值的起始角标

max:最大和

maxOri:最大和子数组起始角标

maxEnd:最大和子数组结尾角标

*/

int add=0,ori=0,max=0,maxOri=0,maxEnd=0;

bool firstPos=true;

//遍历

for(int i =0;i

//遇到正数

if(oriArray[i]>=0){

add+=oriArray[i];//不断累加

if(firstPos){//遇到的第一个正数要记录下标

ori=i;

firstPos=false;

}

}else{

//遇到负数

//之与前的可能最大和比较,若变大,则取代!

if(add>max){

max=add;

maxOri=ori;

maxEnd=i-1;

}

/**

判断累加的值与负数大小关系

如果累加值大于负数,则继续累加

如果累加值小于等于负数,舍弃此负数,向前移动,累加值清零

*/

if(oriArray[i]+add>0){

add+=oriArray[i];

}else{

add=0;

if(i+1

ori=i+1;

}

}

}

//跳出循环后再判断一次

if(add>max){

max=add;

maxOri=ori;

maxEnd=oriArray.size()-1;

}

cout<

cout<

cout<

cout<

for(int i=maxOri;i>=maxOri&&i<=maxEnd;i++){

cout<

}

system("pause");

}

运行图

0818b9ca8b590ca3270a3433284dd417.png

此题的关键在于发现最大和子数组的两端不能是负数这个规律。

做完之后在网上找了找类似的题目答案,发现有大神给出了更牛的解法,在此共享一下

思路2:

当前面的几个数,加起来后,b<0后,

把 b 重新赋值,置为下一个元素,b=a[i]。

当 b>sum,则更新 sum=b;

若 b

源代码2:

#include

#include

#include

#include

using namespace std;

/**

输入一个整形数组,数组里有正数也有负数。

数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。

求所有子数组的和的最大值。要求时间复杂度为 O(n)。

例如输入的数组为 1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为 3, 10, -4, 7, 2,

因此输出为该子数组的和 18。

思路

当前面的几个数,加起来后,b<0后,

把 b 重新赋值,置为下一个元素,b=a[i]。

当 b>sum,则更新 sum=b;

若 b

*/

int maxSum(int* a, int n)

{

int sum=0;

int b=0;

for(int i=0; i

{

if(b<=0) //前面的几个数,加起来后,b<0

b=a[i];//b 重新赋值

else

b+=a[i];//前面的几个数,加起来后,b>=0,继续累加

if(sum

sum=b;// b>sum,则更新 sum=b

}

return sum;

}

void main()

{

int a[10]={1,-8,6,3,-1,5,7,-2,0,1};

cout<

system("pause");

}

解法二之所以比解法一简练,在于他不仅仅意识到两端的数不能为负数,而且只要那一串的子数组相加小于0,就不可能是最大和子数组的一部分。

每个问题都有其发生的规律,设计算法的过程就是发现规律并加以利用的过程。

就好比打羽毛球,如果我发现只要我一回高远球,对手就放短球,那么我下次回完高远就直接冲到网前准备扑杀。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用以下代码实现两个数组相加: ```c #include <stdio.h> int main() { int arr1[] = {1, 2, 3, 4, 5}; int arr2[] = {6, 7, 8, 9, 10}; int sum[5]; int i; for (i = ; i < 5; i++) { sum[i] = arr1[i] + arr2[i]; } printf("Sum of arrays: "); for (i = ; i < 5; i++) { printf("%d ", sum[i]); } return ; } ``` 这段代码定义了两个数组 `arr1` 和 `arr2`,并将它们的对应元素相加存储到另一个数组 `sum` 。最后,使用循环遍历 `sum` 数组并输出结果。 ### 回答2: 下面是使用C语言编写数组数组相加的代码示例: ```c #include <stdio.h> #define SIZE 3 void addArrays(int arr1[], int arr2[], int result[]) { for (int i = 0; i < SIZE; i++) { result[i] = arr1[i] + arr2[i]; } } int main() { int array1[SIZE] = {1, 2, 3}; int array2[SIZE] = {4, 5, 6}; int sum[SIZE]; addArrays(array1, array2, sum); printf("相加后的数组为:"); for (int i = 0; i < SIZE; i++) { printf("%d ", sum[i]); } return 0; } ``` 这段代码,我们定义了一个`addArrays`函,该函接收两个输入数组`arr1`和`arr2`,以及一个结果数组`result`。在函内部,使用`for`循环遍历数组的每个元素,将相应位置上的元素相加,并将结果存储在`result`数组中。 在`main`函,我们声明了两个输入数组`array1`和`array2`,并使用`addArrays`函将它们相加,将结果存储在`sum`数组中。最后,使用`for`循环打印出相加后的数组元素。 运行代码,将会输出以下结果: ``` 相加后的数组为:5 7 9 ``` 这正是数组`array1`和`array2`的对应位置上的元素相加的结果。 ### 回答3: 使用C语言编写数组相加的代码,首先需要定义两个数组,分别为数组A和数组B,并确定数组的大小。然后通过循环遍历两个数组,将对应位置的元素相加,并将结果存储在一个新的数组中。 下面是一个简单的示例代码: ```c #include <stdio.h> #define SIZE 5 // 数组大小为5 int main() { int arrayA[SIZE] = {1, 2, 3, 4, 5}; // 数组A int arrayB[SIZE] = {6, 7, 8, 9, 10}; // 数组B int result[SIZE]; // 存储数组相加的结果 // 数组相加 for (int i = 0; i < SIZE; i++) { result[i] = arrayA[i] + arrayB[i]; } // 打印数组相加的结果 printf("数组相加的结果为:"); for (int i = 0; i < SIZE; i++) { printf("%d ", result[i]); } return 0; } ``` 在上述代码,我们定义了两个大小为5的数组`arrayA`和`arrayB`,并指定了初始值。然后我们定义了一个结果数组`result`来存储两个数组对应位置元素相加的结果。通过使用循环,我们遍历数组A和数组B,并将对应位置的元素相加,并将结果存储在结果数组中。最后,我们通过循环打印出数组相加的结果。 该示例代码只是一个简单的示例,你可以根据自己的需要来调整数组的大小和初始值,并根据实际情况处理数组相加操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值