算法笔记1-最大子序列和问题的求解

问题——

给定N个整数(有可能是负数)A1,A2,A3,A4...An,求最大子序列和。

(子序列必须是连续的);比如,对于输入,-2,11,-4,13,-5,-2;这个序列,

答案是20,即从A2到A4。

对于这个问题,你怎么想的呢?下面有四种解法,看看你的解法是不是其中之一。

解法一、穷举

解题思路——

既然是求某一个连续的子序列的最大和,那么我们把所有的子序列的和都加一遍,然后用一个变量来存储最大的和值,当遍历一遍所有子序列,即可得到最大的和。由于这个子序列长度可以是1,也可以是N,因此需要三重循环。

具体程序——

 private static int calOne(int[] list){
    	int maxSum = 0;
    	for (int i = 0; i < list.length; i++) {
	for (int j = i; j < list.length; j++) {
		int thisSum = 0;
		for (int k = i; k < j; k++) {
			thisSum += list[k];
		}
		if (thisSum > maxSum) {
			maxSum = thisSum;
		}
	}
	}
    	return maxSum;
    }

测试——

为了测试其性能,构建大量数据比较耗费时间,所以这里我让它重复计算某一个数组1万次。

   public static void main(String[] args)  {
       int[] test = {-2,11,-4,13,-5,-219,23,234,-190,280,-20,1340,123,-324,43,-35};
       long time = System.currentTimeMillis();
       for (int i = 0; i < 9999; i++) {
    	   calOne(test);
	}
        System.out.println(calOne(test));
        System.out.println("算法1所用时间:"+(System.currentTimeMillis()-time)+"毫秒");

    }   

结果是:

1790

算法1所用时间:22毫秒

明显,三重循环,其运行时间是O(N^3);

解法二、改进的穷举

通过观察,我们发现,其实第三重循环是不必要的,因为第二次循环已经计算了第三次循环的数值,因此可以撤销。

private static int calTwo(int[] list) {
	int maxSum = 0;
	for (int i = 0; i < list.length; i++) {
	int thisSum = 0;
	for (int j = i; j < list.length; j++) {
		thisSum += list[j];

	if (thisSum > maxSum) {
		maxSum = thisSum;
	}
	}
	}
	return maxSum;
	}

撤销后的时间复制度是O(N^2),我们来看运行时间。

1790

算法2所用时间:6毫秒

确实减少了不少时间,但是这还是很差劲的穷举算法,需要改进。

解法三、联机算法

联机算法优缺点——

在任意时刻,算法对要操作的数据只读入(扫描)一次,一旦被读入并处理,它就不需要在被记忆了。而在此处理过程中算法能对它已经读入的数据立即给出相应子序列问题的正确答案。具有这种特性的算法叫做联机算法(on-line algorithm)。

该算法仅需要常量空间并以线性时间运行,因此联机算法几乎是完美的算法。

优点:占用空间少,所用时间少

缺点:不宜设计,正确性不易观察,同时附加保留信息较少

具体程序——

private static int calThree(int[] list) {
	int maxSum = 0,thisSum = 0;;

		for (int j = 0; j < list.length; j++) {

			thisSum += list[j];

	if (thisSum > maxSum) {
		maxSum = thisSum;
	}else if(thisSum <0){
		thisSum = 0;
	}
	}
	return maxSum;
	}

可以看到,联机算法的时间复杂度是O(N),节省了很多时间。运行验证下。

同样地计算一组数据1万次,结果是——

1790

算法3所用时间:2毫秒

关于这个问题,还有一种分治策略的算法,虽然不如联机算法,但是比起差劲的穷举,还是改进不少的。

以上是个人的读书笔记,书籍为《数据结构与算法描述》。欢迎探讨。

算法笔记1-最大子序列和问题的求解,布布扣,bubuko.com

时间: 2025-01-07 04:18:07

算法笔记1-最大子序列和问题的求解的相关文章

算法笔记之排序

最近在看<算法笔记>,如果单从算法来说,这本书真正做到了短小精悍,首先以排序入题,那么我们今天也来说说排序. 排序 将一堆杂乱无章的元素按照某种规则有序排列的过程就叫"排序".排序是一种非常基础的算法,有着广泛的理论和实践基础.对一个排序算法来说,一般从如下3个方面衡量算法的优劣: 时间复杂度:主要是分析关键字的比较次数和记录的移动次数. 空间复杂度:分析排序算法中需要多少辅助内存 稳定性:若两个记录A和B的关键字值相等,但排序后A.B的先后次序保持不变,则称这种算法是稳定

数据结构与算法笔记 - 绪论

数据结构与算法笔记 - 绪论 1. 什么是计算2. 评判DSA优劣的参照(直尺)3. 度量DSA性能的尺度(刻度)4. DSA的性能度量的方法5. DSA性能的设计及其优化 x1. 理论模型与实际性能的差异x2. DSA优化的极限(下界) 计算机与算法 计算机科学(computer science)的核心在于研究计算方法与过程的规律,而不仅仅是作为计算工具的计算机本身,因此E. Dijkstra及其追随者更倾向于将这门科学称作计算科学(computing science). 计算 = 信息处理

算法笔记-DTW动态时间规整

算法笔记-DTW动态时间规整 简介 简单的例子 定义 讨论 约束条件 步模式 标准化 点与点的距离函数 具体应用场景 分类 点到点匹配 算法笔记-DTW动态时间规整 动态时间规整/规划(Dynamic Time Warping, DTW)是一个比较老的算法,大概在1970年左右被提出来,最早用于处理语音方面识别分类的问题. 1.简介 简单来说,给定两个离散的序列(实际上不一定要与时间有关),DTW能够衡量这两个序列的相似程度,或者说两个序列的距离.同时DTW能够对两个序列的延展或者压缩能够有一定

小算法笔记

素数: 除 1 外只能被 1 和自身整除的数. 方法一: #include <stdio.h> #define N 1000 int num = 0; int prime(int n) { int i; if(n % 2 == 0) return (n == 2); if(n % 3 == 0) return (n == 3); if(n % 5 == 0) return (n == 5); for(i = 7; i*i <= n; ++i) if(n % i == 0) return

算法笔记之堆排序

一.对堆排序的相关了解 1.堆排序的运行时间是 O(nlogn) : 2.定义: 堆heap是一棵具有以下属性的二叉树-- (1)它是一棵完全二叉树: (2)每个结点大于或等于它的任意一个孩子. 备注:完全二叉树的定义--除了最后一层没填满以及最后一层的叶子都是偏左放置的,其他层都是满的二叉树! 3.二叉堆有两种:最大堆和最小堆.在堆排序中我们使用的是最大堆,最小堆常常在构造优先队列时使用. 4.一条路径的深度指的是这条路径的边数,一个结点的深度是指从根结点到该结点的路径的长度. 二.对堆进行排

算法笔记_023:拓扑排序(Java)

目录 1 问题描述 2 解决方案 2.1 基于减治法实现 2.2 基于深度优先查找实现 1 问题描述 给定一个有向图,求取此图的拓扑排序序列. 那么,何为拓扑排序? 定义:将有向图中的顶点以线性方式进行排序.即对于任何连接自顶点u到顶点v的有向边uv,在最后的排序结果中,顶点u总是在顶点v的前面. 2 解决方案 2.1 基于减治法实现 实现原理:不断地做这样一件事,在余下的有向图中求取一个源(source)(PS:定义入度为0的顶点为有向图的源),它是一个没有输入边的顶点,然后把它和所有从它出发

算法笔记_018:旅行商问题(Java)

目录 1 问题描述 2 解决方案 2.1 蛮力法   1 问题描述 何为旅行商问题?按照非专业的说法,这个问题要求找出一条n个给定的城市间的最短路径,使我们在回到触发的城市之前,对每个城市都只访问一次.这样该问题就可以表述为求一个图的最短哈密顿回路的问题.(哈密顿回路:定义为一个对图的每个顶点都只穿越一次的回路) 很容易看出来,哈密顿回路也可以定义为n+1个相邻顶点v1,v2,v3,...,vn,v1的一个序列.其中,序列的第一个顶点和最后一个顶点是相同的,而其它n-1个顶点都是互不相同的.并且

[数据结构和算法]折半插入排序算法笔记

/// <summary> /// 步骤: /// 1.记录当前待排元素 /// 2.标记顺序表有序查找区域下界和上界 /// 3.在顺序表有序查找区域中折半查找等待排序元素的位置 /// 4.把顺序表有序查找区域的某些元素后移一位,以空出位置给等待排序的元素 /// 5.在空出的位置填写当前排序元素 /// </summary> /// <param name="elements"></param> static void SqList

算法笔记2-优先队列(堆)(上)

一.什么是优先队列? 看一情景:我们去KTV唱歌,点歌的时候,可以发现所点的歌就是一个队列. 这时候,一个MM突然不玩手机了想唱歌,于是她来点歌,并且想尽早轮到她. 于是她可以选择"插歌"这个功能插到前排队列里. 这种具备可以插入优先权元素的队列,就叫优先队列.但是,这个定义不是严谨的. 优先队列的基本模型是这样的-- 具备两个功能: insert插入: deleteMin 删除最小者. 它的工作就是-- 它很有用哦,具体可以用在操作系统,外部排序和贪婪算法中等. 二.怎么实现优先队列