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>() { -, -, , , -, , -, - , -, };
List<int> subArray = new List<int>();
if (array.Max() > )
{
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() > )
{
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>() { -, , , -, , -, };
List<List<int>> subArrays = new List<List<int>>();
int subSum = ;
int origin = ;
for (int k = ; 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 - ]);
subSum += array[j - ];
}
subArrays[origin].Add(subSum);
origin++;
subSum = ;
}
}
int max = subArrays[][subArrays[].Count() - ];
int destination = ;
for (int i = ; i < subArrays.Count(); i++)
{
int sumIndex = subArrays[i].Count() - ;
if (subArrays[i][sumIndex] > max)
{
max = subArrays[i][subArrays[i].Count() - ];
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 = ; i < array.Count() - ; i++)
{
Console.Write(array[i]);
Console.Write(" ");
}
Console.WriteLine();
Console.WriteLine("The sum of the array is:" + array[array.Count() - ]);
}
}
}
这里我用了泛型数组的嵌套,因为泛型数组是动态的,所以嵌套的泛型数组就相当于一个动态的二维数组:
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、数组中有正数也有负数,则最大子数组的开头肯定是非负数,结尾也肯定为非负数!也就是说,子数组的核心成员就锁定在那些非负数上。我要找出数组中所有的非负数,记录他们在数组中的位置。最终的目标是计算每两个非负数在数组中的距离。(即两个非负数以及其之间的数所组成的子数组的和)
代码如下:
using System;
using System.Collections.Generic;
using System.Linq; namespace MaxSubarray
{
class Program
{
private static List<int> indexArray = new List<int>();
private static List<int> results = new List<int>();
static void Main(string[] args)
{
//int[] a = { 1, -2, 3, 10, -4, 7, 2, -5 };
int[] a = { -, , , -, , -, };
//Select the ones >=0.
for (int i = ;i< a.Length;i++)
{
if (a[i] > )
{
indexArray.Add(i);
}
}
//Calc all the sums.
CalcResults(a);
//Output the final result.
Console.WriteLine(results.Max());
Console.Read();
} private static void CalcResults(int[] array)
{
int sum;
for (int i = ; i < indexArray.Count(); i++)
{
for (int j = ; j <= i; j++)
{
sum = CalcSum(indexArray[j], indexArray[i], array);
results.Add(sum);
}
}
} private static int CalcSum(int from, int to, int[] array)
{
int sum = ;
for (int i = from; i <= to; i++)
{
sum += array[i];
}
return sum;
}
}
}
这里主要用到了三个方法:
1、方法一:计算数组中两点之间元素所组成的子数组的和;
2、方法二:计算出所有的非负数元素间的组合情况,并用方法一求出两个非负数元素之间所组成的子数组的和;
3、方法三:找出这些和中最大的值就是最大子数组的和。
该方法主要的思想是缩小了搜索范围,分况治之。
C#中求数组的子数组之和的最大值的更多相关文章
- 求数组的子数组之和的最大值II
这次在求数组的子数组之和的最大值的条件下又增加了新的约束: 1.要求数组从文件读取. 2.如果输入的数组很大, 并且有很多大的数字, 就会产生比较大的结果 (考虑一下数的溢出), 请保 ...
- 求数组的子数组之和的最大值III(循环数组)
新的要求:一维数组改成循环数组,只是涉及简单算法,只是拿了小数做测试 想法:从文件读取数组,然后新建数组,将文件读取的数组在新数组中做一下连接,成为二倍长度的数组,然后再遍历,将每次遍历的子数组的和存 ...
- 求数组的子数组之和的最大值IV
在之前的基础上又安排了二维数组的,在课上一开始是理解错要求了,简单的以为用循环数组就能解决,但是却忽视了子数组是否能构成矩形,之后课下和同学们讨论,主要是多重遍历,但是我还是没搞明白怎么构成新的二维数 ...
- N元数组的子数组之和的最大值
题目:有N个整数的元素的一维数组,求子数组中元素之和中最大的一组(思想:动态规划) 分析: 设该数组为array[N], 那么对于array[i]该不该在元素之和最大的那个子数组中呢?首先,不如假设a ...
- Task 4.5 求二维数组中的最大连通子数组之和
任务:输入一个二维整形数组,数组里有正数也有负数. 求所有子数组的和的最大值.要求时间复杂度为O(n). 1.设计思想:因为用之前的解决子数组最大和的问题的思路一直没能解决这个问题,后来看到同学使用将 ...
- 求二维数组联通子数组和的最大值 (联通涂色) beta!
算法十分臃肿,效率捉鸡,不知用了多少循环,还有bug...任重道远,编程之美. 思想:按行遍历,找出每行的最大子数组.若行间都联通,行最大子数组相加后,再加上独立的正数.若行间不连通,找出较大子路径, ...
- [LeetCode] Minimum Size Subarray Sum 最短子数组之和
Given an array of n positive integers and a positive integer s, find the minimal length of a subarra ...
- Minimum Size Subarray Sum 最短子数组之和
题意 Given an array of n positive integers and a positive integer s, find the minimal length of a suba ...
- [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 ...
随机推荐
- Subversion how[Reprint]
1. Subversion简介 Subversion(简称SVN)是一款功能强大的开源版本控制工具,支持Linux和Windows平台. SVN可以有两个访问方式,一种是独立服务器直接访问,即利用 ...
- CSS禅意花园(设计一)
设计 1.排版样式. 正文部分文字比例比菜单不分班的大,可区分着两个区域(说明正文比菜单重要).排版也是一种交流方式,运用文字的大小.间距.颜色调整样式,给浏览者丰富的信息. 2.图标 3.分割线 适 ...
- for穷举
穷举:把所有可能的情况都走一遍,使用if条件筛选出来满足的条件的情况.(把所有的可能性都列举一边) 迭代:从初始情况按照规律不断求解中间情况,最终推导出结果.f foreach 专为数组定义的一种命 ...
- android测试(转)
1.冒烟测试 跟web端的测试流程一样,你拿到一个你们开发做出来的apk首先得去冒烟,也就是保证他的稳定性,指定时间内不会崩溃.这款原生sdk自带的monkey可以当做我们的测试工具.就跟我之前博客所 ...
- javascript 内置对象
什么是对象 javascript中的所有事物都是对象:字符串 数组 数值 函数... 每个对象都带有属性和方法 javascript允许自定义对象 自定义对象: 定义并创建对象实例 使 ...
- JAVA中extends 与implements区别
JAVA中extends 与implements有啥区别?1. 在类的声明中,通过关键字extends来创建一个类的子类.一个类通过关键字implements声明自己使用一个或者多个接口.extend ...
- ThinkPHP讲解(四)——视图
本次讲解主要以<ThinkPHP开发手册>中“模板”一章中讲解为主 在MainController.class.php中新建一个操作方法Test() namespace Home\Cont ...
- 安装 Apache 出现 <OS 10013> 以一种访问权限不允许的方式做了一个访问套接字的尝试
在安装Apache的过程中出现: 仔细查看提示: make_sock: could not bind to address 0.0.0.0:80 恍然大悟,计算机上安装了IIS7,80端口已占用. 打 ...
- U盘启动引导安装linux
一.U盘引导,安装前的准备 1.U盘一枚,至少2G 2.下载并安装虚拟光驱,这里我用的是UltralSO. 二.制作引导盘 1.打开UltraISO软件,选择文件->打开,打开需要烧录的镜像文件 ...
- JSP:一种服务器端动态页面技术的组件规范。
java Servlet page:java服务器端页面,会增加服务器的压力. jsp文件会被容器转换成一个Servlet类然后执行. JSP页面中的注释: HTML注释:<!-- 注释中的ja ...