编程珠玑 第八章 读书笔记

这一章我看的,写的都挺爽快的;
难度不大,但是又非常有意思;
有两点思想被体现:
1.保存状态,避免重复计算;(DB思想);
2.将信息预处理至数据结构中,(打表);
还是看具体问题吧:
求一数组集合中最大的连续子序列:
最垃圾的算法,(n2)
int Oo(int *a, int n)
{
      num =0;
      int i, j,sum=0, max=0;
      for (i=0;i<n; i++)
      {
            for (j=i;j<n; j++)
            {
                  sum+=a[j];
                  max =MAX(sum, max);
            }
            sum =0;
      }
      returnmax;
}
分治法优化:
将序列分为两段A,B,则很明显最大的连续子序列,要么是A中的最大连续子序列,或B,或过中点;
int OO(int *a, int l, int r)
{
      int sum,lmax, rmax, m;
      if(l>r) return 0;//此时 zero element;
      if (l==r)return MAX(0, a[l]);//此时 one element;
      m =(l+r)>>1;//m为l+r 除以二;
      sum = lmax =rmax =0;
      //计算l边从中点起的最大值;
      for (inti=m; i>=l; i--)
      {
            sum+=a[i];
            lmax =MAX(lmax, sum);
      }
      sum =0;
      for (inti=m+1; i<=r; i++)
      {
            sum+=a[i];
            rmax =MAX(rmax, sum);
      }
      returnMAX(MAX((lmax+rmax), OO(a, l, m)),OO(a, m+1, r));
}
最后是线性o(n)算法:(扫描算法)
遇前子序列相加小于0;就重新计算;考虑到负数的因素,这个原因很容易相出来的;
int OOO(int *a, int n)
{
      int i,maxford=0, max=0;
      for(i=0;i<n; i++)
      {
            max =MAX(max+a[i], 0);
            //与每一个截断的自序列做对比;
            maxford =MAX(max, maxford);
      }
      returnmaxford;
}

课后习题:
第五题:
int *cumarr = a+1;
      cout<<cumarr[-1]<<endl;
第九题:
int OOO(int *a, int n)
{
      int i;
      intmaxford=0, max=0;
      int mx =a[0];
      for(i=0;i<n; i++)
      {
            //全是负数的数组,那么最大子序列集合就是其最大值。
            mx =(mx>a[i])?mx:a[i];
            max =(max+a[i]> 0)?(max+a[i]):0;
            //与每一个截断的自序列做对比;
            maxford=(maxford>max)?maxford:max;
      }
      if(mx>0)
      {returnmaxford;}
      else returnmx;
}
第十题:
#include<iostream>
#include<map>
#include<cmath>
using namespace std;
typedef struct
{
      intxi;
      intyj;
}INT;
int OOO(int *a, int n, int t)
{
      intcum[n];
      intde;
      inthr;
      cum[0] =a[0];
      for(int i=1; i<n; i++)
      {
            cum[i] =cum[i-1] + a[i];
      }
      map<int, INT> _map;
      for (intj=n-1; j>0; j--)
      {
            for (inti=0; i<=j-1; i++)
            {
                  hr =abs(cum[(j)]-cum[i]-t);
                  _map[hr].xi= i;
                  _map[hr].yj= j;
            }
      }
      _map[abs(a[0]-t)].yj = 0;
      cout<<"begin:"<<(_map.begin()->second).xi+1<<"end:"<<(_map.begin()->second).yj<<endl;
      if(0 !=((_map.begin()->second).yj))
      de =cum[(_map.begin()->second).yj] -cum[(_map.begin()->second).xi];
      else de =a[0];
      returnde;
}
int main()
{
      inta[10]={31,-41,59,26,-53,58,97,-93,-23,84};
      intn;//你所希望接近的序列值;
      while(cin>>n)
      cout<<OOO(a, 10,n)<<endl;
      return0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值