一,概述

问题:求一维数组中连续子向量的最大和。

例如:a[6]={3,4,-2,-9,10,8}; 则最大连续子向量的和 为 10+8 = 18

1)解法一:简单算法

#include <stdio.h> #define max(a, b) ((a)>(b)?(a):(b)) int main() { int a[6]={3,4,-2,-9,10,8}; int i,j,k; int sum=0; int maxsofar=0; for(i=0;i<6;++i) { for(j=i;j<6;++j) { sum=0; for(k=i;k<=j;++k) { sum+=a[k]; } maxsofar=max(maxsofar,sum); } } printf("max=%d\n",maxsofar); return 0; }       2)两个平方算法

算法一:

#include <stdio.h> #define max(a, b) ((a)>(b)?(a):(b)) int main() { int a[6]={3,4,-2,-9,10,8}; int i,j; int sum=0; int maxsofar=0; for(i=0;i<6;++i) { sum=0; for(j=i;j<6;++j) { sum+=a[j]; maxsofar=max(maxsofar,sum); } } printf("max=%d\n",maxsofar); return 0; }
              算法二:#include <stdio.h> #define max(a, b) ((a)>(b)?(a):(b)) int main() { int a[6]={3,4,-2,-9,10,8}; int cumarr[6]; cumarr[-1]=0; int i,j; int sum=0; int maxsofar=0; for(i=0;i<6;++i) { cumarr[i] = cumarr[i-1] + a[i]; } for(i=0;i<6;++i) { sum=0; for(j=i;j<6;++j) { sum = cumarr[j] - cumarr [i-1]; maxsofar=max(maxsofar,sum); } } printf("max=%d\n",maxsofar); return 0; }

3)分治算法

思想:以m为分界线,最大值有三种情况

一:在m左侧

二:在m右侧

三:跨越m

关键:最初求解左右最大值时候,一定要从中间向两侧递增。看源码解释……

#include "stdio.h" #define max(a,b) a>b?a:b int a[6]={3,4,-2,-9,10,8}; int max2(int a,int b,int c) { if(a>b&&a>c) return a; else if(b>a&&b>c) return b; else return c; } int maxsum(int l,int u) { int i,m,sum,lmax,rmax; if(l>u) return 0; if(l==u) return max(0,a[l]); m=(l+u)/2; lmax = sum =0; for(i=m;i>=l;--i) { sum += a[i]; lmax =max(lmax,sum); } printf("m=:%d\n",m); rmax =sum =0; for(i=m+1;i<=u;++i) { sum += a[i]; rmax =max(rmax,sum); } return max2(lmax + rmax , maxsum(l,m) , maxsum(m+1,u) ); } int main() { int maxsofar=maxsum(0,5); printf("max=%d",maxsofar); return 0; }

【注意】 max2() 如果用宏  #define  max(a,b,c)    max(a,b) >c?max(a,b):c  则不会得到正确结果

4)扫描算法

#include "stdio.h" int main() { int a[6]={3,4,-2,-9,10,8}; int i,sum=0; for(i=0;i<6;++i) { sum+=a[i]; if(sum<0) sum=0; } printf("max=%d",sum); return 0; }

二,总结

优化算法的策略

1)保存已经计算的状态,避免重复计算。

2)将信息预处理到数据结构中。例如算法二

3)分治算法,采取更高级的算法

4)扫描算法,巧妙

5)下界:证明某个匹配的下界,确定最优算法

三,习题

10)可以采用两种方法:O(n*n)

#include <stdio.h> #define min(a, b) ((a)>(b)?(b):(a)) #define obs(a) a>0?a:-a int main() { int a[6]={3,4,-2,-9,10,8}; int i,j,k; int sum=0; int maxsofar=65535;//这个很关键 for(i=0;i<6;++i) { for(j=i;j<6;++j) { sum=0; for(k=i;k<=j;++k) { sum+=a[k]; } maxsofar=min(maxsofar,obs(sum)); } } printf("max=%d\n",maxsofar); return 0; }
返回结果是 1

可以采用O(nlogn)的算法

#include <stdio.h> #define min(a, b) ((a)>(b)?(b):(a)) #define obs(a) a>0?a:-a /*先将 轴 记录在temp 中 先从后面向前找小于轴的 放到第一个(即轴所在位置) 再从前向后找 大于轴的元素 存放到 上一步找到的小于轴的位置 总之:要做的是将后面小于轴的 跟 前面大于轴的 做替换 】 当退出while 循环后 因为最后收场的是 i从低端加上来 所以 i 的位置对应 轴最后要存放的位置*/ int Partition(int a[],int i,int j) { int temp=a[i];//记录下轴的位置 while(i<j) { while(i<j&&temp<=a[j])//将比轴小的 移动到低端 j--; a[i]=a[j];//小的 等于后面的大的 (之后的i 会增加)【后面的大的 移动到前面来后 本趟不会再动】 while(i<j&&temp>=a[i])//将比轴大的 移动到高端 【从前往后找 ,找到 小的往后移动】 i++; a[j]=a[i]; // a[j] 存的 上面找到的小的 (在这里改变)小的等于 前面大的 【】 } a[i]=temp;//轴的位置 return i; } void Quicksort(int a[],int i,int j) { int p; if(i<j) { p=Partition(a,i,j); Quicksort(a,i,p-1); Quicksort(a,p+1,j); } } int main() { int a[6]={3,4,-2,-9,10,8}; int cumarr[6]; cumarr[-1]=0; int i,j; int minsofar=65535; for(i=0;i<6;++i) { cumarr[i] = cumarr[i-1] + a[i]; } Quicksort(cumarr,0,4); for(i=0;i<5;++i) { minsofar=min(minsofar,obs(cumarr[i+1] - cumarr [i])); } printf("min=%d\n",minsofar); return 0; }

返回结果是 1

13)最大子数组问题,给定n*n数组,求矩形子数组的最大总和。

详见博客:http://blog.csdn.net/tianshuai11/article/details/7487882

转载于:https://www.cnblogs.com/JPAORM/archive/2012/05/15/2509994.html

【编程珠玑】第八章 算法设计技术相关推荐

  1. 常用算法设计技术总结

    算法,即计算的方法,使用计算的思想.方法.工具和技术来实现问题求解的思路和途径.计算机提供了计算的能力和硬件设施:算法则提供了计算的思想和软件技术,更好地发挥计算机的潜能. -- 引 有人说,算法无用 ...

  2. 【算法】算法设计技术

    算法设计技巧 文章目录 算法设计技巧 贪心算法(贪婪算法) 多处理器情况 活动选择问题 活动选择问题(加权) 递归解 独立集问题 树上的独立集问题 装箱问题 联机和脱机 近似在线装箱算法 脱机算法 分 ...

  3. 编程珠玑第八章——分治算法求解数组中的最大的连续和

    关键在于把数组分为两个部分a,b.最大的连续和要么在a要么在b,另外还有可能就是跨越a,b的边界,将跨越边界的最大向量称为mc. 一个注意的地方就是mc正在a中的部分包含右边边界的最大子向量,而mc在 ...

  4. 编程珠玑——第八章习题10扩展和习题11

    习题10求解的是查找数组中总和最接近于0的子数组. 们可以尝试使用"将x[0...n-1]扩展为x[0...n]"的思想,建立一个累积和表cumSum进行处理.这里假设输入数组为x ...

  5. 编程珠玑第八章——习题10查找数组中总和最接近0的子数组

    内容来自互联网,做了一定修改 方法1: 这个问题和求子数组最大值优点相似,但解法不同,如果按照求子数组最大值的方法来求解,我们可以求出以j为截止的最大值和最小值,如果最大值和最小值都>0,那么最 ...

  6. 最大字段和各种不同算法实现(参考编程珠玑)

    求最大字段和的算法很好的讲解了算法设计技术.根据<编程珠玑>上的描述,简单实现各种不同的算法.如下: 1.最简单的方法:对所有满足0≤i≤j<n的(i,j)整数进行迭代.对每个整数对 ...

  7. 《编程珠玑》高清pdf版

    下载地址:网盘下载 作者简介 编辑 Jon Bentley是位于新泽西州Murray Hill的朗讯贝尔实验室计算机科学研究中心的技术委员会委员,Jon自1998年就成为Dr. Dobb's Joum ...

  8. 算法设计与分析python_Python算法设计与分析

    内容提要 本书内容包括算法初步.排序算法.查找.双指针问题.哈希算法.深度优先搜索算法.广度优先搜索算法.回溯算法.动态规划.贪心算法.分治算法.并查集.最短路径算法和数论算法等常见算法.每个算法都做 ...

  9. 转自把《编程珠玑》读薄

    http://hawstein.com/posts/make-thiner-programming-pearls.html#Heap 开篇 具体化你的解决的问题.下面是A和B的对话. A:我该如何对磁 ...

最新文章

  1. nix与linux的区别,linux – Nix / OS架构概述?
  2. 单点登录之实战CAS5.1.x(六)——REST协议
  3. 为什么从1970年1月1日开始
  4. bzoj 1974: [Sdoi2010]代码拍卖会
  5. wordpress的下载和安装介绍
  6. linux diff 远程文件,登录diff命令,以单独的文件输出在linux
  7. H3CNE、H3CSE认证考试亲身奋斗过程的心得(拿出来晒晒)
  8. SC_FDE仿真平台:卷积编码 -> 矩阵交织 -> QPSK调制 -> 插入导频 -> 插入CP -> RayleighFading->channel
  9. 在word中快速得到数学公式
  10. 天猫精灵通过私有云控制WiFi设备
  11. 计算机无法检测到键盘,电脑检测不到键盘怎么办
  12. Django中的Model(字段) - 第五轻柔的code - 博客园
  13. 利用python读取excel中的公司名称获取公司的经营范围并回填进excel中
  14. python+opencv+图像特效(图像灰度处理、颜色翻转、图片融合,边缘检测,浮雕效果,颜色映射)
  15. iftop监控网卡实时流量
  16. 先验算法(Apriori Algorithm)原理及python代码实现
  17. 线上问题复盘报告模版
  18. Revit明细表计算重量和明细表导出功能
  19. List集合与Set集合学习笔记
  20. 基于Java的校园一卡通系统

热门文章

  1. 送专利啦~~ .Net高阶异常处理之TopLevelEH
  2. 【恋上数据结构】图基础知识介绍
  3. 【嵌入式】Linux开发工具arm-linux-gcc安装及使用
  4. 如何用ssh工具连接自己的“小米手机”——雷总看了直呼内行!!!
  5. 克罗谈投资策略01_期货交易中的墨菲法则
  6. linux mount_nodev函数,mount()函数 Unix/Linux
  7. web报表工具FineReport的JS编辑框和URL地址栏语法简介
  8. 数据分析方法(一):对比与对标
  9. 读书笔记--云边有个小卖部
  10. vue里面的mvvm双向绑定(高级语法糖)