Task 4.3 求环形数组的最大子数组和

任务要求:输入一个整形数组,数组里有正数也有负数。

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

如果数组A[0]……A[j-1]首尾相邻,允许A[i-1], …… A[n-1], A[0]……A[j-1]之和最大。同时返回最大子数组的位置。

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

1.设计思想:(假设数组长度为n。)任务要求中提出了数组可以首尾相邻,这样在求数组最大子数组和的时候就要考虑两种情况:一是最大子数组和所在数组在A[0]...A[n]之间,不包括首尾相连的情况;二是最大数组和所在数组在A[i-1]...A[n-1],A[0]...A[j-1]之间就要考虑将A[n-1],A[0]连起来。

这时会有几种不同的思路来解决这个问题:(1)在求子数组和的时候让数组自动循环两遍,在第二次到A[n-1]时停止,可控制子数组长度小于n,这时用之前程序中的循环即可求出环形数组中的最大数组和;

(2)将数组自动地延长一倍,(将{a1,a2,a3....an}扩展成{a1,a2,a3...an,a1,a2,a3,...an}),求新的数组的最大数组和,同时也要将求得的子数组长度控制在n以下;

(3)两种方法的实现类似,但是在实现返回子数组的位置时因为数组的元素位置会有变化所以没有实现。于是改变了思路用对立的一种思路考虑问题:对问题之前提到的两种可能情况分别求最大子数组和,第一种就直接用一个循环可以求得和,勇士可以记录组数组的首尾位置;第二种情况可以先求出数组中的最小子数组和minsum,再用整个数组和减去它求出的就是最大子数组和,同时再记录下最小子数组和数组的首尾位置,换算一下就会得到最大子数组和的数组位置。

2.源代码:

//求数组中连续子数组的最大和(测试后)
//刘子晗   2015/4/12
#include <iostream>
#include <time.h>
using namespace std;

void main()
{
    int i, length, max, sum = 0;
    int head = 0;
    int tail = 0;
    int head1 = 0;
    int tail1 = 0;
    int arr[100];
    srand((unsigned)time(NULL));
    cout << "请输入数组长度:";
    cin >> length;
    for (i = 0; i < length; i++)
    {
        arr[i] = rand() % 20 - 10;
        c7out << arr[i] << "  ";
    }//输出随机产生的数组
    cout << endl;
    int max1 = arr[0];
    int min = arr[0];

    for (i = 0; i < length; i++)
    {
        if (sum <= 0)
        {
            sum = arr[i];
            head = i;
        }
        else
        {
            sum = sum + arr[i];
        }
        if ( sum > max1)
        {
            max1 = sum;
            tail = i;
        }
    }
    cout << "最大子数组和不包括收尾相连的部分时,最大值为:" << max1 << endl;

    for (i = 0; i < length; i++)
    {
        if (sum >= 0)
        {
            sum = arr[i];
            head1 = i;
        }
        else
        {
            sum = sum + arr[i];

        }
        if (sum < min)
        {
            min = sum;
            tail1 = i;
        }
    }
    int sum1 = 0;
    for (i = 0; i < length; i++)
    {
        sum1 = sum1 + arr[i];
    }
    int max2 = sum1 - min;
    cout << "最大子数组和包括收尾相连的部分时,最大值为:" << max2 << endl;
    cout << endl;
    if (max1 >= max2)
    {
        cout << "综合两种情况可得最大子数组为:";
        max = max1;
        cout << "arr[" << head + 1 << "]  --  arr[" << tail + 1 << "]" << endl;
        for (int j = head; j <= tail; j++)
        {
            cout << arr[j] << " ";
        }
    }
    else
    {
        max = max2;
        cout << "综合两种情况可得最大子数组为:" ;
        cout << "arr[" << tail1 + 2 << "]  --  arr[" << head1 << "]" << endl;
        for (int j = tail1 + 1; j < length ; j++)
        {
            cout << arr[j] << "  ";
        }

        for (int j = 0; j < head1 ; j++)
        {
            cout << arr[j] << "  ";
        }
    }

    cout << "子数组和的最大值为:" << max;

}    

3.截图:

4.总结:(1)当某一项工程要同时实现件功能时,要对过程采取相应的取舍,某个功能不能实现时,可以改变其他部分的实现方式以实现该功能;

(2)在实现过程中要树立一种从对立面上的角度看问题的思维即逆向思维,这个题目在求第二种的和时,通过求最小和间接得到最大和,就从中巧妙地减少了很大的运算量,是一种很好的方法。

时间: 2024-08-03 12:28:10

Task 4.3 求环形数组的最大子数组和的相关文章

结对开发(求二维首尾相接数组的最大子数组和)

一.题目要求 输入一个二维整形数组,数组里有正数也有负数. 二维数组首尾相接,象个一条首尾相接带子一样. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 求所有子数组的和的最大值. 要求时间复杂度为O(n)题目:返回一个二维整数数组中最大子数组的和 一.设计思想 求环形二维数组最大子数组的和,可以转化为求一维数组最大子数组的和 我们有一个最初的二维数组a[n][n]找它的 最大子数组之和 1.我们先建立一个新的二维数组b[n][2*n-1], 2,这个新的二维数组就是将初始的二

输出一维环形数组中最大子数组和最大子数组的位置

组员 石鹤李海超 一.题目 输出一维环形数组中最大子数组的和 和最大子数组的位置 二.设计思想 把原数组扩大一倍,再把原数组放到后边,只需改变上次试验是循环变量即可求出最大子数组的和. 三.源代码 #include<iostream.h> #include<time.h> #include<stdlib.h> int main() { int arry[20]; int start,end,i; long sum,max; cout<<"Pleas

求数组中最大子数组的和(二维环)

成员:林彦汝.张金 (这次角色调换,我主要负责代码复审,代码测试计划:张金负责程序分析,代码编程.) 题目: 返回一个二维整数数组中最大子数组的和 要求: 输入一个二维整形数组,数组里有正数也有负数. 二维数组首尾相接,象个一条首尾相接带子一样. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 求所有子数组的和的最大值. 思路: 在求一维环形数组和二维数组最大子数组的和的基础上,我们将两个的方法综合起来求解关于二维环形数组.假设原二维数组a[3][3]为 1 -2 3 1 -3

环形数组的最大子数组之和

上次课老师留了求一个数组的最大子数组之和,这次题目要求变化了一下,数组变成了环形的数组.主要的设计思想利用动态规划,非环形数组的任意一个元素只要判断前面的元素之和是否大于0就可以了,环形数组则还要判断数组元素后面的元素之和与0的关系.把数组复制一遍,用另外一个数组记录,从每个数组元素开头的子数组元素的个数不能超过数组的元素个数,否则就会多加某些元素. package Arraysum_circle; import java.math.*; public class FindClass_circl

结对编程之求首尾相连数组中最大子数组的和

1.题目: 返回一个整数数组中最大子数组的和. 2.要求: 输入一个整形数组,数组里有正数也有负数.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.如果数组A[0]……A[j-1]首尾相邻,允许A[i-1], …… A[n-1], A[0]……A[j-1]之和最大.同时返回最大子数组的位置.求所有子数组的和的最大值.要求时间复杂度为O(n). 3.设计思想: 分情况讨论最大子数组可能出现的情况,第一种为正常情况,没有超过数组范围,第二种则比较复杂,要用到环的一部分元素,分而求出两

环形数组的最大子数组求解

然后再用一维数组求解最大子数组的方法即可.值得注意的是,子数组的长度不可超过n,在我程序中有所体现.最终,因为没有要求时间复杂度的问题,我选择 了遍历的方法求解了此问题. 1 #include<iostream> 2 using namespace std; 3 int main() 4 { 5 int n; 6 cout<<"输入环形数组的长度:"; 7 cin>>n; 8 int *p; 9 p=new int[n]; 10 for(int i=

返回一个整数数组中最大子数组的和(三)--环形

这次,在上次的要求中又多了一个条件 ——要求这个数组是环形的. 在上次的基础上,将这个代码进行改进,得到以下结果.下面把代码贴出来. 1 package yiweishuzu; 2 3 import java.util.Scanner; 4 5 public class shuzu_3 { 6 private static Scanner scan; 7 8 public static void main(String[] args) { 9 // 确定元素的个数 10 System.out.p

[经典面试题][淘宝]求首尾相连数组的最大子数组和

题目 给定一个由N个整数元素组成的数组arr,数组中有正数也有负数,这个数组不是一般的数组,其首尾是相连的.数组中一个或多个连续元素可以组成一个子数组,其中存在这样的子数组arr[i],-arr[n-1],arr[0],-,arr[j],现在请你这个ACM_Lover用一个最高效的方法帮忙找出所有连续子数组和的最大值(如果数组中的元素全部为负数,则最大和为0,即一个也没有选). 输入: 输入包含多个测试用例,每个测试用例共有两行,第一行是一个整数n(1<=n<= 100000),表示数组的长度

求一维数组的最大子数组1(结对开发)

题目:返回一个整数数组中最大子数组的和. 要求: 输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 求所有子数组的和的最大值.要求时间复杂度为O(n) 发表一篇博客文章讲述设计思想,出现的问题,可能的解决方案(多选).源代码.结果截图.总结. 结对开发的伙伴: 博客名:Mr.缪 姓名:缪金敏 链接:http://www.cnblogs.com/miaojinmin799/ 分析: 如果按照最笨的方法就是一个一个的比较先比较一个数的然后二个