C#中求数组的子数组之和的最大值

《编程之美》183页,问题2.14——求子数组的字数组之和的最大值。(整数数组)

我开始以为可以从数组中随意抽调元素组成子数组,于是就有了一种想法,把最大的元素抽出来,判断是大于0还是小于等于0,如果大于0就对除了这个最大值外剩下的数组部分进行递归:

using System;
using System.Collections.Generic;
using System.Linq;

namespace MaxSumSubArray
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> array = new List<int>() { -1, -2, 1, 2, -1, 1, -3, 6 - 3, -4, 1 };
            List<int> subArray = new List<int>();
            if (array.Max() > 0)
            {
                MaxSumSubArray(array, subArray);
                PrintArray(subArray);
            }
            else
            {
                Console.Write("The max sub-array is {" + array.Max() + "}");
            }
            Console.ReadLine();
        }

        private static void PrintArray(List<int> subArray)
        {
            Console.WriteLine("The max-sum sub-array is:");
            foreach (int num in subArray)
            {
                Console.Write(num);
                Console.Write(" ");
            }
        }

        private static void MaxSumSubArray(List<int> array, List<int> subArray)
        {
            if (array.Max() > 0)
            {
                subArray.Add(array.Max());
                array.Remove(array.Max());
                MaxSumSubArray(array,subArray);
            }
        }
    }
}

这样做其实就是我想麻烦了,因为最后的结果证明,这样做和遍历数组把大于0的元素都抽出来是一样的,根本用不着递归:

如果数组中没有正整数,那就变成求数组中最大值的问题了。T.T

后来看答案发现,题中说的子数组还必须得是连续的,不能随便抽调。于是开始重新想问题……

我发现,连续子数组的和是不是最大的,要把所有的子数组都找出来以后才能确定。

那没什么好办法了,只能遍历了,首先从第一个元素开始,第一个子数组就是第一个元素本身,第二个子数组就是第一个元素和第二个元素组成的,第三个……

然后从第二个元素开始……

等把这些子数组都列出来以后,分别加和,比较一下哪个最大哪个就是目标子数组了。

代码如下:

using System;
using System.Collections.Generic;
using System.Linq;

namespace MaxSumSubArray
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> array = new List<int>() { -2, 5, 3, -6, 4, -8, 6 };
            List<List<int>> subArrays = new List<List<int>>();
            int subSum = 0;
            int origin = 0;
            for (int k = 1; k <= array.Count(); k++)
            {
                for (int i = k; i <= array.Count(); i++)
                {
                    subArrays.Add(new List<int>());
                    for (int j = k; j <= i; j++)
                    {
                        subArrays[origin].Add(array[j - 1]);
                        subSum += array[j - 1];
                    }
                    subArrays[origin].Add(subSum);
                    origin++;
                    subSum = 0;
                }
            }
            int max = subArrays[0][subArrays[0].Count() - 1];
            int destination = 0;
            for (int i = 0; i < subArrays.Count(); i++)
            {
                int sumIndex = subArrays[i].Count() - 1;
                if (subArrays[i][sumIndex] > max)
                {
                    max = subArrays[i][subArrays[i].Count() - 1];
                    destination = i;
                }
            }
            PrintArray(subArrays[destination]);
            Console.ReadLine();
        }

        private static void PrintArray(List<int> array)
        {
            Console.WriteLine("The max-sum sub-array is:");
            for (int i = 0; i < array.Count() - 1; i++)
            {
                Console.Write(array[i]);
                Console.Write(" ");
            }
            Console.WriteLine();
            Console.WriteLine("The sum of the array is:" + array[array.Count() - 1]);
        }
    }
}

这里我用了泛型数组的嵌套,因为泛型数组是动态的,所以嵌套的泛型数组就相当于一个动态的二维数组:

List<List<int>> subArrays = new List<List<int>>();

subArrays数组中每一个元素都是一个整型数组List<int>。

接下来是三层for循环:

最内层的for循环就是从数组的某一个元素一直加到某一个元素;

中层for循环是从数组某一个元素开始,一直到最后一个元素;

最外层的for循环是用来指定子数组的首元素。

通过三层for循环就可以求出所有的子数组以及他们的和,我把每一个子数组都做为一个元素存在List<int>型数组中,并且int型数组中的最后一位元素用来存子数组的和。

接下来我们遍历所有子数组的末尾元素,比较出所有子数组中和最大的子数组并将其打印。

至此,我们就求出了数组中和最大的子数组:

以上就是经过我的思考所得出的解法。对比书中的解法发现我的解法基本上是书中写的没有优化过的解法一,但细节实现不一样,我的方法不光可以找出最大子数组和,还可以打印对应数组。书中说可以省略一层for循环来避免重复计算对算法进行优化,但是我没想通,改成书中说的那样发现测试结果不对。如果哪位高手有好意见,请给出优化代码。QQQ~!

时间: 2024-10-12 11:25:14

C#中求数组的子数组之和的最大值的相关文章

编程之美之2.14 求数组的子数组之和的最大值

[题目] 一个有N个整数元素的一维数组(A[0],A[1],A[2],...A[n-1]),这个数组中当然有很多子数组,那么子数组之和的最大值是多少? 该子数组是连续的. 我们先来明确一下题意: (1)子数组意味着是连续的. (2)题目只需要求和,并不需要返回子数组的具体位置. (3)数组的元素是整数,所以数组可能包含正整数,负整数或者零. 举几个例子: 数组:[1,-2,3,5,-3,2]返回8 数组:[0,-2,3,5,-1,2]返回9 数组:[-9,-2,-3,-5,-3]返回8 [解法一

编程之美2.14 求数组的子数组之和的最大值

问题描述: 一个有N个整数元素的一维数组(A[0], A[1], A[2],...,A[n-1]),这个数组当然有很多子数组,那么子数组之和的最大值是什么呢? 解法: 1. 暴力解法-------O(N^3) 2. 改进版暴力解法-------O(N^2) *3. 分治算法-------O(NlogN)(暂时未去实现) 4. 数组间关系法-------O(N) 具体思路和代码: 1.暴力解法 思路:Sum[i,...,j]为数组第i个元素到第j个元素的和,遍历所有可能的Sum[i,...,j].

[编程之美] 2.14 求数组的子数组之和的最大值

问题描述:给定一个包含N个整数的数组,求数组的子数组之和的最大值. 这是递归和贪心策略的一个经典问题.现在,对这个问题进行一下总结. 1 明确题意 题目中的子数组要求是连续的,也就是数组中的某个连续部分. 如果数组中都是正整数,直接相加就行.因此,主要是要考虑负数的情况. 2 直接求所有的子数组和 最简单且容易理解的解法是求出所有的子数组和,然后保存最大的和. int MaxSum(int *A, int n) { int maximum = -INF; int sum = 0; int i =

求数组的子数组之和的最大值?

自己写的代码考虑未周全,引入了额外的空间复杂度: //求数组的子数组之和的最大值 #include <iostream> #define N 12 using namespace std; int main() { //int a[]={-5,2,3,-3,-2,3,1,-5}; //int a[]={-5,2,0,3,-2,3,4,5}; int a[]={1,-2,3,10,-4,7,2,-5}; int flag,max,i,j=0; int sum[N]={0}; //(1)记录子数组

第2章 数字之魅——求数组的子数组之和的最大值

求数组的子数组之和的最大值 问题描述 分析与解法 [解法一] 具体代码如下: 1 package chapter2shuzizhimei.maxsumsubarray; 2 /** 3 * 求数组的子数组之和的最大值 4 * [解法一] 5 * @author DELL 6 * 7 */ 8 public class MaxSumSubArray1 { 9 //求数组的子数组之和的最大值 10 public static double maxSum(double a[]){ 11 double

2.14 求数组的子数组之和的最大值

题目:给定一个一维数组,求这个数组的子数组之和的最大值. 最佳方法:动态规划! 一. 可以将一个大问题(N个元素数组)转化为一个较小的问题(N-1个元素数组).. 假设已经知道(A[1],...A[n-1])中最大的子数组的和为:All[1] 并且已经知道(A[1],...A[n-1])中包括A[1]的子数组的最大和为start[1] 所以最终的解All[0] = max(A[0], A[0]+start[1], All[1]) 所以通过DP来求解! 代码如下: #include <iostre

编程之美 2.14求数组的子数组之和的最大值

对于一个有N个元素的数组,a[0]~a[n-1],求子数组最大值. 如:数组A[] = [−2, 1, −3, 4, −1, 2, 1, −5, 4],则连续的子序列[4,−1,2,1]有最大的和6. 方法一:暴力 循环遍历,输出所有,判断最大的和 1 #include"iostream" 2 #define MAX 1001 3 using namespace std; 4 5 int main(){ 6 int n, a[MAX], sum , maxsum ; 7 8 cin &

【编程之美】求数组的子数组之和的最大值

一个有N个整数元素的一维数组A[0],A[1],......,A[n-1],这个数组当然有很多子数组,那么子数组的最大值是什么呢? 分析与解法 我们先明确题意: 1. 题目说的子数组,是连续的: 2. 题目只需要求和,并不需要返回子数组的具体位置: 3. 数组中的元素是整数,所以数组可能包含有正整数.零.负整数: 4. 子数组不为空. 解法一:枚举 最简单的办法就是枚举所有的i和j,计算sum[i..j] = A[i]+A[i+1]+...+A[j],遍历所有可能的sum[i..j],找到最大值

《编程之美》解题报告:2.14 求数组的子数组之和的最大值

引言 ? ? 本文用了五种方法来求解这道题,从最初的n^3的复杂度到后面的n的复杂度,分别用到了递推公式.分而治之以及动态规划的方法去一步步降低算法的复杂度. ? ? 解题报告 ? ? 首先我们很容易想到的一个解法就是三层遍历,首先子数组必定是连续的一串值,相当于从原数组array的下标范围0~n-1中选出i和j,去算arra[i]~array[j]的和,于是我们可以得到最初的第一个解法 ? ? public static int sol1(int[] array) { int lenght =