基础算法简介

一,倍增

从字面的上意思看就是成倍的增长 ,这是指我们在进行递推时,如果状态空间很大,通常的线性递推无法满足时间和空间复杂度的要求 ,那么我们就可以通过成倍的增长,只递推状态空间中在 2 的整数次幂位置上的值作为代表 。

倍增” 与 “二进制划分” 两个思想 互相结合,降低了求解很多问题的 时间 与 空间复杂度

具体的问题有:

快速幂;求解RMQ(区间最值)问题;求解最近公共祖先(LCA)等在树上的倍增应用等

 二,前缀和

前缀和是指某序列的前n项和,可以把它理解为数学上的数列的前n项和。

1.一维前缀和:

预处理O(n):S[i] = a[1]+...+a[i]

查询O(1):a[r]+...+a[l] = S[l] - S[r-1]

2.二维前缀和

预处理O(nm):S[i][j] = S[i-1][j] + S[i][j-1] + a[i][j] - S[i-1][j-1]

查询O(1):[x1:x2,y1:y2]的子矩阵的和 = S[x2][y2] - S[x1-1][y2] - S[x2][y1-1] + S[x1-1][y1-1]

三,差分

差分可以看成前缀和的逆运算,类似于数学中的求导和积分。

1.一维差分

给定一个原数组a

构造一个数组b

使得a[i] = b[1] + b[2] + ... + b[i],即a数组是b数组的前缀和数组,b数组是a数组的差分数组

已知a数组的情况下:

预处理O(n):b[i] = a[i] - a[i-1]

例题

给a数组[l,r]区间中的每个数加上c,只需要 b[l] + c,b[r+1] - c 即可。

b[l] + c 则a数组区间[l:]中的每个数都会+c

b[r+1] - c 则a数组区间[r+1:]中的每个数都会-c

使得仅有区间[l,r]中的数+c

倘若有m个区间,时间复杂度为O(2*n + m);若暴力求解,时间复杂度为O(n*m)

2.二维差分

二维数组a是数组b的前缀和数组,b是a的差分数组。

void insert(int x1,int y1,int x2,int y2,int c)
{     //对b数组执行插入操作,等价于对a数组中的(x1,y1)到(x2,y2)之间的元素都加上了c
    b[x1][y1] += c;
    b[x2 + 1][y1] -= c;
    b[x1][y2 + 1] -= c;
    b[x2 + 1][y2 + 1] += c;
}

已知a数组求b数组:

方法一:

先假想a数组为空,那么b数组一开始也为空,但是实际上a数组并不为空,因此我们每次让以(i,j)为左上角到以(i,j)为右下角面积内元素(其实就是一个小方格的面积)去插入 c = a[i][j] ,等价于原数组a中(i,j) 到(i,j)范围内 加上了 a[i][j] ,因此执行 n*m次插入操作,就成功构建了差分b数组.

  for(int i = 1;i <= n;i++)
  {
      for(int j = 1;j <= m;j++)
      {
          insert(i, j, i, j, a[i][j]);    //构建差分数组
      }
  }

方法二:

直接构造的方法

b[i][j] = a[i][j] - a[i-1][j] - a[i][j-1] + a[i-1][j-1]

四,离散化

把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。

适用范围:数组中元素值域很大,但个数不是很多。
比如将a[]=[1,3,100,2000,500000]映射到[0,1,2,3,4]这个过程就叫离散化。

离散化常与差分、前缀和、数组数组、线段树结合考查。

五,二分

二分题目主要分为二分查找二分答案,二分类型分为整数二分实数域上二分

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值