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

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4.  
  5. namespace MaxSumSubArray
  6. {
  7. class Program
  8. {
  9. static void Main(string[] args)
  10. {
  11. List<int> array = new List<int>() { -, -, , , -, , -, - , -, };
  12. List<int> subArray = new List<int>();
  13. if (array.Max() > )
  14. {
  15. MaxSumSubArray(array, subArray);
  16. PrintArray(subArray);
  17. }
  18. else
  19. {
  20. Console.Write("The max sub-array is {" + array.Max() + "}");
  21. }
  22. Console.ReadLine();
  23. }
  24.  
  25. private static void PrintArray(List<int> subArray)
  26. {
  27. Console.WriteLine("The max-sum sub-array is:");
  28. foreach (int num in subArray)
  29. {
  30. Console.Write(num);
  31. Console.Write(" ");
  32. }
  33. }
  34.  
  35. private static void MaxSumSubArray(List<int> array, List<int> subArray)
  36. {
  37. if (array.Max() > )
  38. {
  39. subArray.Add(array.Max());
  40. array.Remove(array.Max());
  41. MaxSumSubArray(array,subArray);
  42. }
  43. }
  44. }
  45. }

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

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

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

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

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

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

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

代码如下:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4.  
  5. namespace MaxSumSubArray
  6. {
  7. class Program
  8. {
  9. static void Main(string[] args)
  10. {
  11. List<int> array = new List<int>() { -, , , -, , -, };
  12. List<List<int>> subArrays = new List<List<int>>();
  13. int subSum = ;
  14. int origin = ;
  15. for (int k = ; k <= array.Count(); k++)
  16. {
  17. for (int i = k; i <= array.Count(); i++)
  18. {
  19. subArrays.Add(new List<int>());
  20. for (int j = k; j <= i; j++)
  21. {
  22. subArrays[origin].Add(array[j - ]);
  23. subSum += array[j - ];
  24. }
  25. subArrays[origin].Add(subSum);
  26. origin++;
  27. subSum = ;
  28. }
  29. }
  30. int max = subArrays[][subArrays[].Count() - ];
  31. int destination = ;
  32. for (int i = ; i < subArrays.Count(); i++)
  33. {
  34. int sumIndex = subArrays[i].Count() - ;
  35. if (subArrays[i][sumIndex] > max)
  36. {
  37. max = subArrays[i][subArrays[i].Count() - ];
  38. destination = i;
  39. }
  40. }
  41. PrintArray(subArrays[destination]);
  42. Console.ReadLine();
  43. }
  44.  
  45. private static void PrintArray(List<int> array)
  46. {
  47. Console.WriteLine("The max-sum sub-array is:");
  48. for (int i = ; i < array.Count() - ; i++)
  49. {
  50. Console.Write(array[i]);
  51. Console.Write(" ");
  52. }
  53. Console.WriteLine();
  54. Console.WriteLine("The sum of the array is:" + array[array.Count() - ]);
  55. }
  56. }
  57. }

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

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

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

接下来是三层for循环:

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

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

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

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

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

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

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


2015.12.29我又在网上看到了这个题,于是又经过一番思考,得出了一种新的解法,思路如下:

1、如果数组中全是非正数,则最大子数组就是该数组的最大值。这种情况下,根本就不需要继续遍历,极大的减少了计算量,直接得出答案。

2、如果数组中全是非负数,则最大字数组就是该数组本身。这种情况下,根本就不需要继续遍历,极大的减少了计算量,直接得出答案。

3、数组中有正数也有负数,则最大子数组的开头肯定是非负数,结尾也肯定为非负数!也就是说,子数组的核心成员就锁定在那些非负数上。我要找出数组中所有的非负数,记录他们在数组中的位置。最终的目标是计算每两个非负数在数组中的距离。(即两个非负数以及其之间的数所组成的子数组的和)

代码如下:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4.  
  5. namespace MaxSubarray
  6. {
  7. class Program
  8. {
  9. private static List<int> indexArray = new List<int>();
  10. private static List<int> results = new List<int>();
  11. static void Main(string[] args)
  12. {
  13. //int[] a = { 1, -2, 3, 10, -4, 7, 2, -5 };
  14. int[] a = { -, , , -, , -, };
  15. //Select the ones >=0.
  16. for (int i = ;i< a.Length;i++)
  17. {
  18. if (a[i] > )
  19. {
  20. indexArray.Add(i);
  21. }
  22. }
  23. //Calc all the sums.
  24. CalcResults(a);
  25. //Output the final result.
  26. Console.WriteLine(results.Max());
  27. Console.Read();
  28. }
  29.  
  30. private static void CalcResults(int[] array)
  31. {
  32. int sum;
  33. for (int i = ; i < indexArray.Count(); i++)
  34. {
  35. for (int j = ; j <= i; j++)
  36. {
  37. sum = CalcSum(indexArray[j], indexArray[i], array);
  38. results.Add(sum);
  39. }
  40. }
  41. }
  42.  
  43. private static int CalcSum(int from, int to, int[] array)
  44. {
  45. int sum = ;
  46. for (int i = from; i <= to; i++)
  47. {
  48. sum += array[i];
  49. }
  50. return sum;
  51. }
  52. }
  53. }

这里主要用到了三个方法:

1、方法一:计算数组中两点之间元素所组成的子数组的和;

2、方法二:计算出所有的非负数元素间的组合情况,并用方法一求出两个非负数元素之间所组成的子数组的和;

3、方法三:找出这些和中最大的值就是最大子数组的和。

该方法主要的思想是缩小了搜索范围,分况治之。

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

  1. 求数组的子数组之和的最大值II

    这次在求数组的子数组之和的最大值的条件下又增加了新的约束:  1.要求数组从文件读取.      2.如果输入的数组很大,  并且有很多大的数字,  就会产生比较大的结果 (考虑一下数的溢出), 请保 ...

  2. 求数组的子数组之和的最大值III(循环数组)

    新的要求:一维数组改成循环数组,只是涉及简单算法,只是拿了小数做测试 想法:从文件读取数组,然后新建数组,将文件读取的数组在新数组中做一下连接,成为二倍长度的数组,然后再遍历,将每次遍历的子数组的和存 ...

  3. 求数组的子数组之和的最大值IV

    在之前的基础上又安排了二维数组的,在课上一开始是理解错要求了,简单的以为用循环数组就能解决,但是却忽视了子数组是否能构成矩形,之后课下和同学们讨论,主要是多重遍历,但是我还是没搞明白怎么构成新的二维数 ...

  4. N元数组的子数组之和的最大值

    题目:有N个整数的元素的一维数组,求子数组中元素之和中最大的一组(思想:动态规划) 分析: 设该数组为array[N], 那么对于array[i]该不该在元素之和最大的那个子数组中呢?首先,不如假设a ...

  5. Task 4.5 求二维数组中的最大连通子数组之和

    任务:输入一个二维整形数组,数组里有正数也有负数. 求所有子数组的和的最大值.要求时间复杂度为O(n). 1.设计思想:因为用之前的解决子数组最大和的问题的思路一直没能解决这个问题,后来看到同学使用将 ...

  6. 求二维数组联通子数组和的最大值 (联通涂色) beta!

    算法十分臃肿,效率捉鸡,不知用了多少循环,还有bug...任重道远,编程之美. 思想:按行遍历,找出每行的最大子数组.若行间都联通,行最大子数组相加后,再加上独立的正数.若行间不连通,找出较大子路径, ...

  7. [LeetCode] Minimum Size Subarray Sum 最短子数组之和

    Given an array of n positive integers and a positive integer s, find the minimal length of a subarra ...

  8. Minimum Size Subarray Sum 最短子数组之和

    题意 Given an array of n positive integers and a positive integer s, find the minimal length of a suba ...

  9. [LeetCode] 209. Minimum Size Subarray Sum 最短子数组之和

    Given an array of n positive integers and a positive integer s, find the minimal length of a contigu ...

随机推荐

  1. HTML调用servlet(二)

    5.修改数据 5.1编写查询条件页面 修改单条数据的时候,首先是查询出单个数据的详细信息,然后根据实际需要部分修改或者全部修改.修改之后,数据会提交到数据库,数据库中保存更新以后的数据. 查询出单条数 ...

  2. 最大权闭合图hdu3996

    定义:最大权闭合图:是有向图的一个点集,且该点集的所有出边都指向该集合.即闭合图内任意点的集合也在改闭合图内,给每个点分配一个点权值Pu,最大权闭合图就是使闭合图的点权之和最大. 最小割建边方式:源点 ...

  3. .net开发之我见,or实现 最简 优化法。knock out type convert 与我之简化orm的实现原理及实现细则,最简化开发法

    现在的.net or构架,大家认同的各种大大小小,ef,subsonic,nhibernate,甚至小一些的petapoco这种,但用过的人我想他们考虑的是比较多. 小一些的Petapoco也有几千行 ...

  4. [原创]java WEB学习笔记91:Hibernate学习之路-- -HQL 迫切左外连接,左外连接,迫切内连接,内连接,关联级别运行时的检索策略 比较。理论,在于理解

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  5. 认真学习shell的第一天-数学运算

    shell中的数学运算有三种方式: (1)let,用let的时候,变量名称前不用添加$ (2)[],[]中变量可使用也可不使用$ (3)(())变量名之前必须添加$

  6. 。。。Hibernate 查询数据 事务管理。。。

    在Hibernate中,查询数据的时候,可能会需要事务的管理,为什么呢?因为在查询数据库的时候,Hibernate将数据从数据库里面查询出来之后,会先把数据放入Hibernate的session缓存里 ...

  7. oracle 的索引

    一.索引分类      按逻辑分: 单列索引(Single column):  单列索引是基于单列所创建的索引 复合(多列)索引(Concatenated ): 复合索引是基于两列或者多列所创建的索引 ...

  8. 夺命雷公狗TP下关联查询

    记录下我们常用的关联查询: public function add4(){ $id=$_GET['id']; $this->list = M("student")->t ...

  9. 夺命雷公狗---微信开发54----微信js-sdk接口开发(1)之快速入门

    js-sdk基本介绍 除去服务号的九大接口外,微信提供了JS-SDK接口,所谓JS-SDK接口也就是在网页中使用javascript来更改网页设置, (比如隐藏右上角的菜单)获取用户状态(比如地理位置 ...

  10. 【GDI+】 线段 文字 定位的问题(二)

    继续: 经过上文的分析,似乎可以得到类似这样的想法: 由此 分为左右两侧进行区分绘制,应该就可以获得想要的结果了~