连续性问题有哪些,求最大连续数

  连续性问题有哪些,求最大连续数

  给出一个长度为n的序列A 1,A 2,…,n,求最大连续和。换句话说,要求找到1=i=j=n,使得阿伊阿伊1…阿j尽量大。暴力枚举实现#包括输入输出流

  使用命名空间标准

  int A[50]={5,9,7,3,4,1,5,8,6,7,3,6,4,0,8,6,7 };

  int main()

  {

  int n=50

  int tot=0;

  int best=A[0];

  //初始化最大值,为了防止连续和小于0,所以必须初始化为一个[0].

  for(int I=0;I n;我)

  {

  for(int j=I;j n;j)

  {//检查连续子序列A[i],…,A[j]

  int sum=0;

  for(int k=I;k=j;k)

  {//累加元素和

  sum=A[k];

  小孩

  }

  如果(最佳求和)

  {

  最佳=总和;

  }

  }

  }

  cout best= best tot= tot endl;

  返回0;

  }tot与机器的运行速度无关。

  不同机器的速度不一样,运行时间也会有所差异,但小孩的值一定相同。

  换句话说,它去掉了机器相关的因素,只衡量算法的"工作量"大小,

  具体来说,是"加法"操作的次数。

  算法分析:1.第一层循环遍历数组A的我位从0到n,是最大连续和的左起点;

  2.第二层循环遍历数组A的j位从我到n,是最大连续和的右终点;

  3.第三层循环遍历数组A的k位从我到j,求出当前范围内的连续和;

  4.公式:设输入规模为n时的加法操作次数

  连续子序列之和等于两个前缀和之差实现#包括输入输出流

  使用命名空间标准

  int A[50]={5,9,7,3,4,1,5,8,6,7,3,6,4,0,8,6,7 };

  int S[50];

  int main()

  {

  int n=50,best=A[0];

  s[0]=0;

  for(int I=0;I n;我)

  {

  S[I]=S[I-1]A[I];

  //递推前缀和S

  }

  for(int I=0;I n;我)

  {

  for(int j=I;j n;j)

  {

  best=max(best,S[j]-S[I-1]);

  //更新最大值

  }

  }

  cout best= best endl

  返回0;

  }算法分析:S[i]表示第一个数到第我个数的和S[j]-S[i-1]表示第我个数到第j个数列的和。

  分治算法实现#包括输入输出流

  使用命名空间标准

  int A[50]={5,9,7,3,4,1,5,8,6,7,3,6,4,0,8,6,7 };

  int maxsum(int *A,int x,int y)

  {//返回数组在左闭右开区间[x,y]中的最大连续和

  如果(y-x==1)返回一个[x];//只有一个元素,直接返回。

  int m=x(y-x)/2;

  //分治第一步:划分成[x,m]和[m,y]

  int maxs=max(maxsum(A,x,m),maxsum(A,m,y));

  //分治第二步:递归求解

  int v,L,R;

  v=0,L=A[m-1];

  //分治第三步:合并(1)——从分界点开始往左的最大连续和L

  for(int I=m-1;I=x;我-)

  {

  L=max(L,v=A[I]);

  }

  v=0,R=A[m];

  //分支第三步:合并(2)——从分界点开始往右的最大连续和稀有

  for(int I=m;I y;我)

  {

  R=max(R,v=A[I]);

  }

  return max(maxs,L R);//把子问题的解与L和稀有比较

  }

  int main()

  {

  cout maxsum(A,0,51)endl;

  返回0;

  }分治算法实现:

  1.划分问题:把序列分成元素个数尽量相等的两半;

  2.递归求解:分别求出完全位于左半或者完全位于右半的最佳序列;

  3.合并问题:求出起点位于左半,终点位于右半的最大连续和序列,并和子问题的最优解比较。

  思路分析首先,我们可以把整个数列平均分成左右两部分,答案则会在以下三种情况中:

  1、所求数列完全包含在左半部分的数列中。

  2、所求数列完全包含在右半部分的数列中。

  3、所求数列刚好横跨分割点,即左右数列各占一部分。

  前两种情况和大问题一样,只是规模小了些,如果三个子问题都能解决,那么答案就是三个结果的最大值。

  计算出:以分割点为起点向左的最大连续数列和、以分割点为起点向右的最大连续数列和,这两个结果的和就是第三种情况的答案。因为已知起点,所以这两个结果都能在O(N)的时间复杂度能算出来。

  算法分析:用递归的思路进行分析,设序列长度为n时T(n)=2T(n/2) n,T(1)=1;

  其中2T(n/2)是两次长度为n/2的递归调用,而最后的n是合并的时间(整个序列恰好扫描一遍)。

  注意分界点应当是x和y的平均数m=x (y-x)/2,这是因为运算符"/"的"取整"朝零方向(趋向于零)

  圆形,不是圆形向下。使用x (y-x)/2确保边界点总是靠近间隔的开始。

  #include iostream的动态规划和实施

  使用命名空间std

  int A[50]={0,5,9,7,3,4,1,5,8,6,7,3,6,4,0,8,6,7 };

  int main()

  {

  int ans=A[1];

  for(int I=1;i 50我)

  {

  if(A[I-1]0)A[I]=A[I-1];

  else A[I]=0;

  if(A[I]ans)ans=A[I];

  }

  cout ans endl

  返回0;

  }算法分析用dp[n]表示以第n个数结尾的最大连续子序列之和,所以有如下递推公式:

  dp[n]=max(0,dp[n-1]) num[n]

  整个问题的答案是max(dp[m]) m[1,N]。

  大道至简3354完美解决方案实现#包括iostream

  使用命名空间std

  int main()

  {

  int N,N,s,ans,m=0;

  CIN N N;//读取数组长度和序列中的第一个数字

  ans=s=n;//将ans初始化为序列中的第一个数字

  for(int I=1;I N;我)

  {

  if(s m)m=s;

  CIN n;s=n;

  如果(s-m ans)

  ans=s-m;

  }

  cout ans endl

  返回0;

  }给定一个sum数组,sum[i]表示第1个数到第I个数的和,所以sum[j]-sum[i-1]表示第I个数到第j个数的和。

  以第n个数结尾的最大子序列。假设这个子序列的起点是M,结果是sum[n]-sum[m-1]。

  并且,sum[m]必须是sum[1],sum[2]…sum[n-1]中的最小值。

  这样,如果在保持计算的和数组的同时,保持前面的最小值,那么答案就出来了。

  在计算前缀和的过程中,保持之前获得的最小值。

  其时间复杂度为O(N),空间复杂度为O(1),达到理论下限!

  大连,最后一个问题,解决了!

  转载请联系作者取得转载授权,否则将追究法律责任。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • office2010激活密钥大全 怎么永久激活office2010
  • project2010产品密钥免费_project2010激活密钥永久激活码
  • c语言调用退出函数 c语言退出整个程序怎么写
  • c语言中怎么给函数初始化 c语言的初始化语句
  • c语言编写函数计算平均值 c语言求平均函数
  • chatgpt是什么?为什么这么火?
  • ChatGPT为什么注册不了?OpenAI ChatGPT的账号哪里可以注册?
  • OpenAI ChatGPT怎么注册账号?ChatGPT账号注册教程
  • chatgpt什么意思,什么是ChatGPT ?
  • CAD中怎么复制图形标注尺寸不变,CAD中怎么复制图形线性不变
  • cad中怎么创建并使用脚本文件,cad怎么运行脚本
  • cad中快速计算器的功能,cad怎么快速计算
  • cad中快速修改单位的方法有哪些,cad中快速修改单位的方法是
  • cad中心点画椭圆怎么做,cad轴测图怎么画椭圆
  • CAD中常用的快捷键,cad各种快捷键的用法
  • 留言与评论(共有 条评论)
       
    验证码: