等差数列和特殊矩阵压缩公式/下标计数公式的应用
等差数列和特殊矩阵压缩公式/下标计数公式的应用
ref
等差数列
递推公式
-
a
n
=
a
n
−
1
+
d
;
(
n
=
2
,
3
,
.
.
.
)
a_n=a_{n-1}+d;(n=2,3,...)
an=an−1+d;(n=2,3,...)
- 注意,有的时候d是一个负值
- 此外,由数列的和的定义可知:
- 对于任何数列 , 总是有 a n = s n − s n − 1 ; ( n = 2 , 3 , . . . ) ; s n 表示前 n 项和 对于任何数列,总是有a_n=s_n-s_{n-1};(n=2,3,...);s_n表示前n项和 对于任何数列,总是有an=sn−sn−1;(n=2,3,...);sn表示前n项和
- 有时候会很有用,比如在推导排序不等式的时候
通项
-
相关公式和性质可以有通项公式推导
-
a n = a 1 + ( n − 1 ) d ; n = 1 , 2 , 3 , . . . a n = a 1 + n d − d = d n + ( a 1 − d ) ; ( 将 n 视为变量 ) 那么对于任何 f ( x ) = k x + b , 都可以看做是一个等差数列的通项 d = k ; a 1 − d = b ; ( a 1 = b + d ) a_n=a_1+(n-1)d ;n=1,2,3,... \\ a_n=a_1+nd-d=dn+(a_1-d);(将n视为变量) \\那么对于任何f(x)=kx+b,都可以看做是一个等差数列的通项 \\d=k;a_1-d=b;(a_1=b+d) an=a1+(n−1)d;n=1,2,3,...an=a1+nd−d=dn+(a1−d);(将n视为变量)那么对于任何f(x)=kx+b,都可以看做是一个等差数列的通项d=k;a1−d=b;(a1=b+d)
-
相邻项的性质
- a n = a n − 1 + a n + 1 2 ; n = 2 , 3 , . . . a_n=\frac{a_{n-1}+a_{n+1}}{2};n=2,3,... an=2an−1+an+1;n=2,3,...
- a n + a m = a q + a p ; ( m + n = p + q = t 常数 ) a_n+a_m=a_q+a_p;(m+n=p+q=t常数) an+am=aq+ap;(m+n=p+q=t常数)
等差数列和
-
由通向公式 a n = a 1 + ( n − 1 ) d a 1 = a 1 + 0 d a 2 = a 1 + d a 3 = a 1 + 2 d . . . a n = a 1 + ( n − 1 ) d s = ∑ i = 1 n a i = ∑ i = 1 n ( a 1 + ( n − 1 ) d ) = a 1 ∑ i = 1 n 1 + d ∑ i = 1 n ( n − 1 ) = n a 1 + d ( n − 1 ) + ( n − 2 ) + . . . + 0 2 = n a 1 + d n ( n − 1 ) 2 \\由通向公式a_n=a_1+(n-1)d \\a_1=a_1+0d \\a_2=a_1+d \\a_3=a_1+2d \\... \\a_n=a_1+(n-1)d \\s=\sum\limits_{i=1}^{n}a_i=\sum\limits_{i=1}^{n}(a_1+(n-1)d) =a_1\sum\limits_{i=1}^{n}1+d\sum\limits_{i=1}^{n}(n-1)\\ =na_1+d\frac{(n-1)+(n-2)+...+0}{2} \\=na_1+d\frac{n(n-1)}{2} 由通向公式an=a1+(n−1)da1=a1+0da2=a1+da3=a1+2d...an=a1+(n−1)ds=i=1∑nai=i=1∑n(a1+(n−1)d)=a1i=1∑n1+di=1∑n(n−1)=na1+d2(n−1)+(n−2)+...+0=na1+d2n(n−1)
或者
s = n ( a 1 + a n ) 2 另外 , 对于等差数列 , 如果 x + y = t ; ( t 为常数 ) 那么根据通向公式有 a x + a y = 2 a 1 + ( t − 2 ) d ( 是一个常数 ) 当 t 取 n + 1 时 : a x + a y = 2 a 1 + ( n − 1 ) d 因此 , 有倒序相加是 2 s 可得到 : s = n ( a 1 + a n ) 2 = n ( a x + a n + 1 − x ) 2 s=n\frac{(a_1+a_n)}{2} \\另外,对于等差数列,如果x+y=t;(t为常数) \\那么根据通向公式有a_x+a_y=2a_1+(t-2)d(是一个常数) \\当t取n+1时:a_x+a_y=2a_1+(n-1)d \\因此,有倒序相加是2s可得到:s=n\frac{(a_1+a_n)}{2}=n\frac{(a_x+a_{n+1-x})}{2} s=n2(a1+an)另外,对于等差数列,如果x+y=t;(t为常数)那么根据通向公式有ax+ay=2a1+(t−2)d(是一个常数)当t取n+1时:ax+ay=2a1+(n−1)d因此,有倒序相加是2s可得到:s=n2(a1+an)=n2(ax+an+1−x)
等差求和公式的应用
- 假设函数 f ( x ) 用表格法可以做如下的描述 ; 其中 i , n 为常数 假设函数f(x)用表格法可以做如下的描述;其中i,n为常数 假设函数f(x)用表格法可以做如下的描述;其中i,n为常数
x x x | f ( x ) f(x) f(x) |
---|---|
1 | n n n |
2 | n − 1 n-1 n−1 |
3 3 3 | n − 2 n-2 n−2 |
… | … |
i | n − ( i − 1 ) n-(i-1) n−(i−1) |
-
也就是说 f ( x ) = n − ( x − 1 ) = n + 1 − x 也就是说f(x)=n-(x-1)=n+1-x 也就是说f(x)=n−(x−1)=n+1−x
-
可以看出 f ( x ) 是一个公差为 d = − 1 的等差数列 可以看出f(x)是一个公差为d=-1的等差数列 可以看出f(x)是一个公差为d=−1的等差数列
-
f ( x ) 前 i 项和为 s i = i a 1 + d i ( i − 1 ) 2 = i n + ( − 1 ) i ( i − 1 ) 2 = 1 2 i ( 2 n − i + 1 ) f(x)前i项和为s_i=ia_1+d\frac{i(i-1)}{2}=in+(-1)\frac{i(i-1)}{2}=\frac{1}{2}i(2n-i+1) f(x)前i项和为si=ia1+d2i(i−1)=in+(−1)2i(i−1)=21i(2n−i+1)
- 或者 , 如果我们写出了第 i 项的 f ( x ) = n − ( i − 1 ) , s i = 1 2 n ( a 1 + a n ) = 1 2 i ( 2 n − i + 1 ) 或者,如果我们写出了第i项的f(x)=n-(i-1), \\s_i=\frac{1}{2}n(a_1+a_n)=\frac{1}{2}i(2n-i+1) 或者,如果我们写出了第i项的f(x)=n−(i−1),si=21n(a1+an)=21i(2n−i+1)
-
在上三角矩阵解压缩公式中,上述 i ( i ) = i − 1 i(i)=i-1 i(i)=i−1公式取
- a i , j = B [ k ] , ( i ⩽ j , i 是从 1 开始计数的矩阵行坐标 ) 函数 k ( i , j ) 表示元素 a i , j 被压缩到数组 B 中的那个位置 ( 下标值 ) 而根据压缩算法 , 这个值就是矩阵中 , a i , j 前面的元素个数 k ( i , j ) = 1 2 ( i − 1 ) ( 2 n − i + 2 ) + ( j − i ) a_{i,j}=B[k],(i\leqslant j,i是从1开始计数的矩阵行坐标) \\函数k(i,j)表示元素a_{i,j}被压缩到数组B中的那个位置(下标值) \\而根据压缩算法,这个值就是矩阵中,a_{i,j}前面的元素个数 \\k(i,j)=\frac{1}{2}(i-1)(2n-i+2)+(j-i) ai,j=B[k],(i⩽j,i是从1开始计数的矩阵行坐标)函数k(i,j)表示元素ai,j被压缩到数组B中的那个位置(下标值)而根据压缩算法,这个值就是矩阵中,ai,j前面的元素个数k(i,j)=21(i−1)(2n−i+2)+(j−i)
数列/数组游标计数公式
问题对象
- 设自然数序列 1 , 2 , 3 , 4 , . . . , p − 1 , p , . . . , n − 1 , n ⏟ 共计 m 个元素 ; 其中 p < n 设自然数序列1,2,3,4,...,p-1,\underset{共计m个元素}{\underbrace{p,...,n-1,n}};其中p<n 设自然数序列1,2,3,4,...,p−1,共计m个元素 p,...,n−1,n;其中p<n
- 更一般序列形式:
序列
{
a
n
}
=
⋯
,
a
1
,
a
2
,
a
3
,
⋯
,
a
p
,
⋯
,
a
q
,
⋯
;
序列\{a_n\}=\cdots,a_1,a_2,a_3,\cdots,a_p,\cdots,a_q,\cdots;
序列{an}=⋯,a1,a2,a3,⋯,ap,⋯,aq,⋯;
- 下标 ( i n d e x i ) 体现了元素间的先后关系和相邻关系 下标(index_i)体现了元素间的先后关系和相邻关系 下标(indexi)体现了元素间的先后关系和相邻关系
问题内容
- 这是一维序列区间计数公式的相关讨论
-
主要包括:
-
知道闭区间两端元素的序号,求区间内包含多少个元素
-
知道区间长度和区间的一个断点序号(坐标)求另一个端点的序号
-
- 尽管看起来讨论这种问题有点幼稚,但是为了提高解题效率,还是值得整理的
问题变体
- 开区间容易转化为闭区间问题,下面的实例中将会看到
A指针序号差/地址增量偏移/坐标计算offset
-
这一部分是讨论由区间长度计算另一端坐标的问题
-
区间&坐标问题本质的表现之一
-
**增量 Δ = e n d − s t a r t \Delta=end-start Δ=end−start**在这个问题上是一个核心概念
- 为了便于使用,我们也叫做
序号差(坐标差)
- 增量有正负之分
- 序号沿着增大的方向变化的, 称为正增量 Δ > 0 称为正增量\Delta>0 称为正增量Δ>0
- 沿着负方向减小的方向变化的, 称为负增量 Δ < 0 称为负增量\Delta<0 称为负增量Δ<0
- 为了便于使用,我们也叫做
-
a 1 , a 2 , ⋯ , a n a_1,a_2,\cdots,a_n a1,a2,⋯,an
-
a i a i + 1 ⋯ a j − 1 a j ⏟ 子串长度为 Δ = j − i a_i\underbrace{a_{i+1}\cdots a_{j-1}a_{j}}_{子串长度为\Delta=j-i} ai子串长度为Δ=j−i ai+1⋯aj−1aj
-
增量区间内 Δ = j − i 内的元素不包括 a i ; 即 , 仅包括 [ a i + 1 , a j ] 增量区间内\Delta=j-i内的元素不包括a_i;即,仅包括[a_{i+1},a_{j}] 增量区间内Δ=j−i内的元素不包括ai;即,仅包括[ai+1,aj]
-
或者 a i a i + 1 ⋯ a j − 1 ⏟ 负增量 Δ = i − j a j \underbrace{a_ia_{i+1}\cdots a_{j-1}}_{负增量\Delta=i-j}a_{j} 负增量Δ=i−j aiai+1⋯aj−1aj
-
由于 a i ∼ a j − 1 共有 L 个元素 ; 每数一下 , 序号在 y 的基础上 − 1 元素 : 序号 a j : y a j − 1 : y − 1 a j − 2 : y − 2 ⋮ a i + 1 : y − ( L − 1 ) a i : y − ( L ) 即 x = y − L 由于a_i\sim a_{j-1}共有L个元素;每数一下,序号在y的基础上-1 \\元素:序号 \\a_{j}:y \\a_{j-1}:y-1 \\a_{j-2}:y-2 \\\vdots \\a_{i+1}:y-(L-1) \\a_{i}:y-(L) \\即x=y-L 由于ai∼aj−1共有L个元素;每数一下,序号在y的基础上−1元素:序号aj:yaj−1:y−1aj−2:y−2⋮ai+1:y−(L−1)ai:y−(L)即x=y−L
-
特别的 , 当 L = 1 有 a i a j ⏟ L = 1 特别的,当L=1有a_i\underbrace{a_{j}}_{L=1} 特别的,当L=1有aiL=1 aj
-
-
-
o f f s e t = L = Δ = j − i ; offset=L=\Delta=j-i; offset=L=Δ=j−i;
-
结合下面的描述, ∣ Δ ∣ = ∣ j − i ∣ |\Delta|=|j-i| ∣Δ∣=∣j−i∣可以理解为:
-
元素 [ a i + 1 , a j ] 闭区间内元素数目 ∣ Δ ∣ 元素[a_{i+1},a_{j}]闭区间内元素数目|\Delta| 元素[ai+1,aj]闭区间内元素数目∣Δ∣
-
或者理解为指针从 a i 移动到 a j 需要执行单步移动次数 或者理解为指针从a_i移动到a_j需要执行单步移动次数 或者理解为指针从ai移动到aj需要执行单步移动次数
-
设 a i 的序号为 x ; a j 的序号为 y ; 设a_i的序号为x;a_j的序号为y; 设ai的序号为x;aj的序号为y;
- 那么 y = x + Δ ; 或者 x = y − Δ 那么y=x+\Delta;或者x=y-\Delta 那么y=x+Δ;或者x=y−Δ
- 特别的 Δ = 1 , y = x + 1 ; x = y − 1 特别的\Delta=1,y=x+1;x=y-1 特别的Δ=1,y=x+1;x=y−1
-
-
★ a i + Δ = a i + Δ ; 表示指向 a i 的指针经过正方向偏移 L 次 ( 其中每次偏移 , 指针从前一个元素移动到相邻的后一个元素 , 下标 ( 序号 ) 变化 1 ) \bigstar\ a_i+\Delta=a_{i+\Delta}; \\表示指向a_i的指针经过正方向偏移L次 \\(其中每次偏移,指针从前一个元素移动到相邻的后一个元素,下标(序号)变化1) ★ ai+Δ=ai+Δ;表示指向ai的指针经过正方向偏移L次(其中每次偏移,指针从前一个元素移动到相邻的后一个元素,下标(序号)变化1)
-
例如 , 当 i = 1 , Δ = 1 时 , p 1 经过一次移动变为 p 2 例如,当i=1,\Delta=1时,p_1经过一次移动变为p_2 例如,当i=1,Δ=1时,p1经过一次移动变为p2
- a 1 ↑ p 1 , a 2 ↑ p 2 , ⋯ , a n \underset{\uparrow_{p_1}}{a_1},\underset{\uparrow_{p_2}}{a_2},\cdots,a_n ↑p1a1,↑p2a2,⋯,an
-
从上面的关系式可以看出, 指针从 a i 移动到 a j 需要执行 Δ = j − i 单步移动操作 ★ 指针从a_i移动到a_j需要执行\Delta=j-i单步移动操作\bigstar 指针从ai移动到aj需要执行Δ=j−i单步移动操作★
-
内存中的数组而言
- 设一个数组元素占用L=3个存储单元
- a 1 , a 2 , a 3 ; a 4 , a 5 , a 6 a_1,a_2,a_3;a_4,a_5,a_6 a1,a2,a3;a4,a5,a6
- 其中 a i 表示第 i 个存储单元 其中a_i表示第i个存储单元 其中ai表示第i个存储单元
-
那么元素
e
0
占用
a
1
,
a
2
,
a
3
;
元素
e
1
占用
a
4
,
a
5
,
a
6
那么元素e_0占用a_1,a_2,a_3;元素e_1占用a_4,a_5,a_6
那么元素e0占用a1,a2,a3;元素e1占用a4,a5,a6
- L o c ( e 0 ) = a 1 , e 0 的起始地址就是 a 1 的地址 Loc(e_0)=a_1,e_0的起始地址就是a_1的地址 Loc(e0)=a1,e0的起始地址就是a1的地址
- L o c ( e 1 ) = a 1 + 1 × L = a 1 + 1 × 3 = a 4 Loc(e_1)=a_1+1\times L=a_1+1\times3=a_4 Loc(e1)=a1+1×L=a1+1×3=a4
- L o c ( e i ) = L o c ( e 0 ) + i × L = a 1 + i L = a 1 + i L Loc(e_i)=Loc(e_0)+i\times L=a_1+iL=a_{1+iL} Loc(ei)=Loc(e0)+i×L=a1+iL=a1+iL
- L o c ( e j ) = L o c ( e i ) + ( j − i ) L Loc(e_j)=Loc(e_i)+(j-i)L Loc(ej)=Loc(ei)+(j−i)L
B闭区间内的元素数量MatchedSize
-
M a t c h e d S i z e ( i n d e x i , i n d e x j ) 表示 , 序列 { a n } 的元素 a i 到元素 a j 之间连同两端包含了多少个元素 MatchedSize(index_i,index_j)表示,序列\{a_n\}的元素a_i到元素a_j之间连同两端包含了多少个元素 MatchedSize(indexi,indexj)表示,序列{an}的元素ai到元素aj之间连同两端包含了多少个元素
-
∣ Δ ∣ = i n c r e m e n t ( i n d e x 1 , i n d e x 2 ) = ∣ i n d e x 2 − i n d e x 1 ∣ m ( s t a r t , e n d ) = M a t c h e d S i z e ( i n d e x 1 , i n d e x 2 ) = ∣ Δ ∣ + 1 = ∣ i n d e x 2 − i n d e x 1 ∣ + 1 |\Delta|=increment(index1,index2)=|index2-index1| \\ m(start,end)=MatchedSize(index1,index2)=|\Delta|+1=|index2-index1|+1 ∣Δ∣=increment(index1,index2)=∣index2−index1∣m(start,end)=MatchedSize(index1,index2)=∣Δ∣+1=∣index2−index1∣+1
-
offset&MatchedSize公式都是十分基础但是用途十分广泛的计数公式,比如
-
活动日期的计算: 11 ∼ 29 号共有几天 ? d a y s = m ( 11 , 29 ) = 29 − 11 + 1 = 19 11\sim29号共有几天?days=m(11,29)=29-11+1=19 11∼29号共有几天?days=m(11,29)=29−11+1=19
-
排列数公式 ( n m ) = n ( n − 1 ) ( n − 2 ) ⋯ ( n − m + 1 ) 排列数公式\binom{n}{m}=n(n-1)(n-2)\cdots(n-m+1) 排列数公式(mn)=n(n−1)(n−2)⋯(n−m+1)
- 则我们有 p − 1 = n − m ( 或者说 ( p − 1 ) + m = n ) ; 这样 , ( p − 1 ) ! = ( n − m ) ! ; ∏ k = 0 m − 1 ( n − k ) = n ! ( n − m ) ! 则我们有p-1=n-m(或者说(p-1)+m=n); \\这样,(p-1)!=(n-m)!; \\ \prod_{k=0}^{m-1}(n-k)=\frac{n!}{(n-m)!} 则我们有p−1=n−m(或者说(p−1)+m=n);这样,(p−1)!=(n−m)!;k=0∏m−1(n−k)=(n−m)!n!
-
模式串匹配算法(朴素匹配/kmp)
-
特殊矩阵压缩/解压公式
-
k对角矩阵,其第i行形如:
- 0 ⋯ 0 , a i , j 1 , ⋯ , a i , j k , 0 ⋯ 0 0\cdots0,a_{i,j_1},\cdots,a_{i,j_k},0\cdots 0 0⋯0,ai,j1,⋯,ai,jk,0⋯0
-
问, a i , j k 前面的非零元素有几个 a_{i,j_k}前面的非零元素有几个 ai,jk前面的非零元素有几个;
-
上面的问题看似不是MatchedSize的应用场合,但其实,稍微想一下,也可以转化为MatchedSize
-
0 ⋯ 0 , a i , j 1 , ⋯ , a i , j k − 1 ⏟ 几个元素 ? , a i , j k , 0 ⋯ 0 0\cdots0,\underbrace{a_{i,j_1},\cdots,a_{i,j_{k-1}}}_{几个元素?},a_{i,j_k},0\cdots 0 0⋯0,几个元素? ai,j1,⋯,ai,jk−1,ai,jk,0⋯0
-
m ( 1 , k − 1 ) = j k − 1 − j 1 + 1 m_{(1,k-1)}=j_{k-1}-j_1+1 m(1,k−1)=jk−1−j1+1
-
特别的 , 三对角矩阵 ( k = 3 ) 中 , 第 i 行元素 a i , j 前面的非零元素有几个 ? 特别的,三对角矩阵(k=3)中,第i行元素a_{i,j}前面的非零元素有几个? 特别的,三对角矩阵(k=3)中,第i行元素ai,j前面的非零元素有几个?
- j 1 = i − 1 , j k − 1 = j − 1 j_1=i-1,j_{k-1}=j-1 j1=i−1,jk−1=j−1
- e l e m s = m ( i − 1 , j − 1 ) = ( j − 1 ) − ( i − 1 ) + 1 = j − i + 1 elems=m(i-1,j-1)=(j-1)-(i-1)+1=j-i+1 elems=m(i−1,j−1)=(j−1)−(i−1)+1=j−i+1
-
-
问: a i ⋯ a j − 1 ⏟ 子串长度为 L a j \underbrace{a_i\cdots a_{j-1}}_{子串长度为L}a_{j} 子串长度为L ai⋯aj−1aj
- 其中 a j 的序号为 y 其中a_j的序号为y 其中aj的序号为y
-
那么
a
i
的序号
x
为多少
?
那么a_i的序号x为多少?
那么ai的序号x为多少?
- 坐标差 Δ = j − i = L 坐标差\Delta=j-i=L 坐标差Δ=j−i=L
-
a
i
a
i
+
1
⋯
a
j
−
1
a
j
⏟
子串长度为
L
+
1
\underbrace{a_ia_{i+1}\cdots a_{j-1}a_{j}}_{子串长度为L+1}
子串长度为L+1
aiai+1⋯aj−1aj
- L + 1 = y − x + 1 即 : x = y − L L+1=y-x+1即: x=y-L L+1=y−x+1即:x=y−L
-
a
i
a
i
+
1
⋯
a
j
−
1
a
j
⏟
子串长度为
L
a_i\underbrace{a_{i+1}\cdots a_{j-1}a_{j}}_{子串长度为L}
ai子串长度为L
ai+1⋯aj−1aj
- x = y − L x=y-L x=y−L
-
-
😎小结
-
从一维序列的计数公式&坐标公式的各种形式上看
-
关系式 ∣ j − i ∣ = ∣ Δ ( L ) ∣ 足以解决所有相关问题 ( 以坐标差 Δ 为核心 ) 关系式|j-i|=|\Delta(L)|足以解决所有相关问题(以坐标差\Delta为核心) 关系式∣j−i∣=∣Δ(L)∣足以解决所有相关问题(以坐标差Δ为核心)
-
坐标差 = 增量长度 j − i = Δ = L [ a i , a j − 1 ] = L [ a j , a i + 1 ] ⩾ 0 ( i − j = − Δ ) (core) \\坐标差=增量长度 \\ j-i=\Delta=L_{[a_{i},a_{j-1}]}=L_{[a_{j},a_{i+1}]}\tag{core}\geqslant 0 \\ (i-j=-\Delta) 坐标差=增量长度j−i=Δ=L[ai,aj−1]=L[aj,ai+1]⩾0(i−j=−Δ)(core)
L [ a i , a j ] = ∣ Δ ∣ + 1 = ∣ j − i ∣ + 1 L_{[a_{i},a_{j}]}=|\Delta|+1=|j-i|+1 L[ai,aj]=∣Δ∣+1=∣j−i∣+1
-
将坐标差 Δ 用闭区间距离 L 或 ( L ± 1 ) 表示出来 将坐标差\Delta用闭区间距离L或(L\pm 1)表示出来 将坐标差Δ用闭区间距离L或(L±1)表示出来
-
L 通常是 a i ∼ a j 闭区间内的元素数量 , 这时候 Δ ( L ) = L − 1 L通常是a_i\sim a_j闭区间内的元素数量,这时候\Delta(L)=L-1 L通常是ai∼aj闭区间内的元素数量,这时候Δ(L)=L−1
-
利用上面的关系式列等式, 所有关于 i , j , L 的值都可以一步计算的时间内得出 所有关于i,j,L的值都可以一步计算的时间内得出 所有关于i,j,L的值都可以一步计算的时间内得出
公式中都具有坐标差(假设i<j)
- 闭区间元素数量 L = Δ + 1 = j − i + 1 闭区间元素数量L=\Delta+1=j-i+1 闭区间元素数量L=Δ+1=j−i+1
- 闭区间左端点坐标 i 可以由 : i = j − Δ = j − L + 1 ; 闭区间左端点坐标i可以由:i=j-\Delta=j-L+1; 闭区间左端点坐标i可以由:i=j−Δ=j−L+1;
- 右端点坐标 j = i + Δ = i + L − 1 右端点坐标j=i+\Delta=i+L-1 右端点坐标j=i+Δ=i+L−1
数组元素位置&起始地址
二维数组(矩阵)
- 按行优先排列
-
m
,
n
分别表示矩阵的行数和列数
m,n分别表示矩阵的行数和列数
m,n分别表示矩阵的行数和列数
- i ∈ [ 0 , m − 1 ] 是行下标的维界 i\in[0,m-1]是行下标的维界 i∈[0,m−1]是行下标的维界
- j ∈ [ 0 , n − 1 ] 是列下标的维界 j\in[0,n-1]是列下标的维界 j∈[0,n−1]是列下标的维界
-
a
i
,
j
表示矩阵中的第
i
行第
j
列元素
a_{i,j}表示矩阵中的第i行第j列元素
ai,j表示矩阵中的第i行第j列元素
- 例如, 第一个元素坐标为 a 00 第一个元素坐标为a_{00} 第一个元素坐标为a00
- L 表示数组中的元素占的存储单元数 , 比如字节数 L表示数组中的元素占的存储单元数,比如字节数 L表示数组中的元素占的存储单元数,比如字节数
- L o c ( a i , j ) 表示元素 a i , j 在内存中的起始地址 Loc(a_{i,j})表示元素a_{i,j}在内存中的起始地址 Loc(ai,j)表示元素ai,j在内存中的起始地址
一维数组
-
按行优先排列
-
m 分别表示一维数组的维数 m分别表示一维数组的维数 m分别表示一维数组的维数
- i ∈ [ 0 , m − 1 ] 是行下标的维界 i\in[0,m-1]是行下标的维界 i∈[0,m−1]是行下标的维界
-
a i 表示数组中下标为 i 的元素 a_{i}表示数组中下标为i的元素 ai表示数组中下标为i的元素
- 例如, 第一个元素坐标为 a 0 第一个元素坐标为a_{0} 第一个元素坐标为a0
-
L 表示数组中的元素占的存储单元数 , 比如字节数 L表示数组中的元素占的存储单元数,比如字节数 L表示数组中的元素占的存储单元数,比如字节数
-
L o c ( a i ) 表示元素 a i 在内存中的起始地址 Loc(a_{i})表示元素a_{i}在内存中的起始地址 Loc(ai)表示元素ai在内存中的起始地址
-
a[0] a[1] a[2] … a[i] -
L o c ( a 1 ) = L o c ( a 0 ) + 1 × L 一种不太准确的 L o c ( a i ) 的理解 : ↿ L a [ 0 ] , a [ 1 ] , ⋯ , a [ i − 1 ] ⏟ i − 1 ⏞ i 个元素 , ↿ a [ i ] , ⋯ 比较合适的理解 L o c ( a i ) : a [ 0 ] ↿ L o c , a [ 1 ] , ⋯ , a [ i − 1 ] ⏟ i − 1 ⏞ i 个元素 , a [ i ] , ⋯ 所以 : L o c ( a i ) = L o c ( a 0 ) + i × L Loc(a_1)=Loc(a_0)+1\times L \\一种不太准确的Loc(a_i)的理解: \\\underset{\underset{L}{\upharpoonleft}}{} \overbrace{a[0],\underbrace{a[1],\cdots,a[i-1]}_{i-1}}^{i个元素},\underset{\upharpoonleft}{}a[i],\cdots \\比较合适的理解Loc(a_i): \\\overbrace{{\underset{\upharpoonleft_{Loc}}{a[0]}},\underbrace{a[1],\cdots,a[i-1]}_{i-1}}^{i个元素},a[i],\cdots \\所以: Loc(a_i)=Loc(a_0)+i\times L Loc(a1)=Loc(a0)+1×L一种不太准确的Loc(ai)的理解:L↿a[0],i−1 a[1],⋯,a[i−1] i个元素,↿a[i],⋯比较合适的理解Loc(ai):↿Loca[0],i−1 a[1],⋯,a[i−1] i个元素,a[i],⋯所以:Loc(ai)=Loc(a0)+i×L
-
-
L o c ( a i ) = L o c ( a 0 ) + i × L Loc(a_i)=Loc(a_0)+i\times L Loc(ai)=Loc(a0)+i×L
-
L o c ( a i , j ) = L o c ( a 0 , 0 ) + i × s i z e o f ( r o w ) + j × L s i z e o f ( r a w ) = m × L L o c ( a i , j ) = L o c ( a 0 , 0 ) + ( i × m + j ) × L Loc(a_{i,j})=Loc(a_{0,0})+i\times sizeof(row)+j\times L \\sizeof(raw)=m\times L \\Loc(a_{i,j})=Loc(a_{0,0})+ (i\times m+j)\times L Loc(ai,j)=Loc(a0,0)+i×sizeof(row)+j×Lsizeof(raw)=m×LLoc(ai,j)=Loc(a0,0)+(i×m+j)×L
三角矩阵的压缩
- 三角矩阵(方阵)
A
[
1...
n
]
[
1...
n
]
A[1...n][1...n]
A[1...n][1...n],包括
- 上三角矩阵(下三角所有元为同一个常量) j ⩽ i j\leqslant i j⩽i
- 下三角矩阵(上三角所有元素为同一个常量) i ⩽ j i\leqslant j i⩽j
- 上下三角包含 n ( n + 1 ) 2 个元素 ; 在加上 ( 占据矩阵其余位置的 ) 一个常量 c 上下三角包含\frac{n(n+1)}{2}个元素;在加上(占据矩阵其余位置的)一个常量c 上下三角包含2n(n+1)个元素;在加上(占据矩阵其余位置的)一个常量c
-
所以需要一个大小
至少
‾
为
n
(
n
+
1
)
2
+
1
维的数组来保存必要元素
所以需要一个大小\underline{至少}为\frac{n(n+1)}{2}+1维的数组来保存必要元素
所以需要一个大小至少为2n(n+1)+1维的数组来保存必要元素
- A 三角 [ 1 , . . . , n ] [ 1 , . . . , n ] ; B [ 1... 1 2 n ( n + 1 ) + 1 ] A_{三角}[1,...,n][1,...,n];B[1...\frac{1}{2}{n(n+1)}+1] A三角[1,...,n][1,...,n];B[1...21n(n+1)+1]
上三角
按行优先
-
从矩阵的第一个元素 a 0 , 0 开始 , 按行扫描 , 一直到 a i , j , 期间遇到的属于上三角 ( a i , j ; i ⩽ j ) 的元素的个数 : 从矩阵的第一个元素a_{0,0}开始,按行扫描,一直到a_{i,j}, \\期间遇到的属于上三角(a_{i,j};i\leqslant j)的元素的个数: \\ 从矩阵的第一个元素a0,0开始,按行扫描,一直到ai,j,期间遇到的属于上三角(ai,j;i⩽j)的元素的个数:
第x行 行x上属于上三角的元素的个数 1 n n n 2 n-1 3 n − 2 n-2 n−2 … … x x x n − ( x − 1 ) n-(x-1) n−(x−1) i − 1 ( x = i − 1 时 ) i-1(x=i-1时) i−1(x=i−1时) n − ( i − 1 − 1 ) = n − i + 2 n-(i-1-1)=n-i+2 n−(i−1−1)=n−i+2 i(特别的) j − i + 1 j-i+1 j−i+1 -
如果 B [ 0... ] , 那么 k 0 = S i − 1 + s i − 1 ; S i − 1 = ( i − 1 ) ( 2 n − i + 2 ) 2 是前 i − 1 行的元素总数量 , s i = j − i + 1 是第 i 行的 a i , i 到 a i , j 的元素数量 k 0 = ( i − 1 ) ( 2 n − i + 2 ) 2 + ( j − i + 1 ) − 1 = ( i − 1 ) ( 2 n − i + 2 ) 2 + j − i 如果B[0...],那么k_0=S_{i-1}+s_i-1; \\S_{i-1}=\frac{(i-1)(2n-i+2)}{2}是前i-1行的元素总数量, \\s_i=j-i+1是第i行的a_{i,i}到a_{i,j}的元素数量 \\k_0=\frac{(i-1)(2n-i+2)}{2}+(j-i+1)-1=\frac{(i-1)(2n-i+2)}{2}+j-i 如果B[0...],那么k0=Si−1+si−1;Si−1=2(i−1)(2n−i+2)是前i−1行的元素总数量,si=j−i+1是第i行的ai,i到ai,j的元素数量k0=2(i−1)(2n−i+2)+(j−i+1)−1=2(i−1)(2n−i+2)+j−i
-
如果 B [ 1... ] , 那么 k 1 = S i − 1 + s i ; k 1 = ( i − 1 ) ( 2 n − i + 2 ) 2 + j − i + 1 如果B[1...],那么k_1=S_{i-1}+s_i; \\k_1=\frac{(i-1)(2n-i+2)}{2}+j-i+1 如果B[1...],那么k1=Si−1+si;k1=2(i−1)(2n−i+2)+j−i+1
-
映射公式用法
k 0 ( i , j ) = { ( i − 1 ) ( 2 n − i + 2 ) 2 + j − i ; ( i ⩽ j ) n ( n + 1 ) 2 ; ( j < i ) 即 A [ i ] [ j ] = B [ k ( i , j ) ] k 根据 B 数组的要求而决定选用 k 0 还是 k 1 ; 实际上更多的用的前者 k_0(i,j)=\begin{cases} \frac{(i-1)(2n-i+2)}{2}+j-i ;(i\leqslant j) \\\frac{n(n+1)}{2};(j<i) \end{cases} \\ 即A[i][j]=B[k(i,j)] \\k根据B数组的要求而决定选用k_0还是k_1;实际上更多的用的前者 k0(i,j)={2(i−1)(2n−i+2)+j−i;(i⩽j)2n(n+1);(j<i)即A[i][j]=B[k(i,j)]k根据B数组的要求而决定选用k0还是k1;实际上更多的用的前者
按列优先
- k 1 ( i , j ) = 1 2 j ( j − 1 ) + i k_1(i,j)=\frac{1}{2}{j(j-1)}+i k1(i,j)=21j(j−1)+i
下三角矩阵
- 和上三角十分相似的讨论过程
- 压缩过程行列情况对调(按行优先/按列优先)
- 本质上是等差数列求和公式的应用
😀公式使用条件
k 0 & k 1 的关系 k_0\&k_1的关系 k0&k1的关系
- 经过前面的讨论, 可以知道 k 0 = k 1 − 1 ; 或者 k 1 = k 0 + 1 可以知道k_0=k_1-1;或者k_1=k_0+1 可以知道k0=k1−1;或者k1=k0+1
- 之后我们仅讨论 k 0 或者 k 1 之后我们仅讨论k_0或者k_1 之后我们仅讨论k0或者k1
A [ 0... ] v s A [ 1... ] A[0...] vs A[1...] A[0...]vsA[1...]
- 有时, 矩阵的坐标是从 0 开始的 : i ∈ [ 0 , n ] , j ∈ [ 0 , n ] 矩阵的坐标是从0开始的:i\in[0,n],j\in[0,n] 矩阵的坐标是从0开始的:i∈[0,n],j∈[0,n]
- 前的公式都是在 i ∈ [ 1 , n ] , j ∈ [ 1 , n ] 情况下推导的 前的公式都是在i\in[1,n],j\in[1,n]情况下推导的 前的公式都是在i∈[1,n],j∈[1,n]情况下推导的
- 如果要求用 a i , j ; i ∈ [ 0 , n ] , j ∈ [ 0 , n ] 来计算 k , 那么必须要一定的调整 如果要求用a_{i,j};i\in[0,n],j\in[0,n]来计算k,那么必须要一定的调整 如果要求用ai,j;i∈[0,n],j∈[0,n]来计算k,那么必须要一定的调整
- 幸运的是,这个调整比较简单, 只需要将 a i , j 直接映射 a i + 1 , j + 1 就可以了 只需要将a_{i,j}直接映射a_{i+1,j+1}就可以了 只需要将ai,j直接映射ai+1,j+1就可以了
对称矩阵
-
对称矩阵和三角矩阵十分相近
-
不同的是对称矩阵的特点: a i , j = a j , i a_{i,j}=a_{j,i} ai,j=aj,i
-
这意味着 , 如果对称矩阵将上三角 ( i ⩽ j ) 压缩到数组 B 中 , 并且要求的是 a p , q ( p ⩾ q ) 的压缩位置 , 那么可以利用公式 a q , p = a p , q 来解压 这意味着,如果对称矩阵将上三角(i\leqslant j)压缩到数组B中, \\并且要求的是a_{p,q}(p\geqslant q)的压缩位置,那么可以利用公式a_{q,p}=a_{p,q}来解压 这意味着,如果对称矩阵将上三角(i⩽j)压缩到数组B中,并且要求的是ap,q(p⩾q)的压缩位置,那么可以利用公式aq,p=ap,q来解压
k 0 ( i , j ) = { i ( i − 1 ) 2 + j − 1 ; i ⩾ j j ( j − 1 ) 2 + i − 1 ; i ⩽ j k_0(i,j)=\begin{cases} \frac{i(i-1)}{2}+j-1;i\geqslant j \\ \frac{j(j-1)}{2}+i-1;i\leqslant j \end{cases} k0(i,j)={2i(i−1)+j−1;i⩾j2j(j−1)+i−1;i⩽j
三对角矩阵
- 对角阵/三对角矩阵均为方阵
- 记为 A n × n 记为A_{n\times n} 记为An×n
- 二维数组形式 A [ 1 , . . . , n ] [ 1 , . . . , n ] 二维数组形式A[1,...,n][1,...,n] 二维数组形式A[1,...,n][1,...,n]
i=1 | ( Q − 1 Q_{-1} Q−1)(虚拟) | Q 0 Q_0 Q0 | Q 1 Q_1 Q1 | ||||
---|---|---|---|---|---|---|---|
2 | Q 2 Q_2 Q2 | Q | Q 4 Q_4 Q4 | ||||
3 | Q 5 Q_5 Q5 | Q | Q 7 Q_7 Q7 | ||||
4 | ⋮ \vdots ⋮ | … | ⋮ \vdots ⋮ | ||||
Q | Q | Q | |||||
Q | Q |
-
第 1 行到 i − 1 行每行多有三个元素 ( 补上的虚拟元素 Q − 1 后面再 − 1 , 则 s i − 1 = 3 ( i − 1 ) − 1 ) 第1行到i-1行每行多有三个元素(补上的虚拟元素Q_{-1}后面再-1,则s_{i-1}=3(i-1)-1) 第1行到i−1行每行多有三个元素(补上的虚拟元素Q−1后面再−1,则si−1=3(i−1)−1)
-
第 i 行有 b i = j − ( i − 1 ) 个元素 第i行有b_i=j-(i-1)个元素 第i行有bi=j−(i−1)个元素
-
因为,三对角矩阵的斜对角区域的每一行的三个元素可以表示为: a i , i − 1 , a i , i , a i , i + 1 a_{i,i-1},a_{i,i},a_{i,i+1} ai,i−1,ai,i,ai,i+1
-
这时
j = { i − 1 i i + 1 j=\begin{cases} i-1 \\i \\i+1 \end{cases} j=⎩ ⎨ ⎧i−1ii+1
-
压缩公式
-
将矩阵 A [ 1 , . . . , n ] [ 1 , . . . , n ] 中的元素 a i , j 压缩到 B 数组中的下标为 k = k ( i , j ) 的位置 将矩阵A[1,...,n][1,...,n]中的元素a_{i,j}压缩到B数组中的下标为k=k(i,j)的位置 将矩阵A[1,...,n][1,...,n]中的元素ai,j压缩到B数组中的下标为k=k(i,j)的位置
-
计算 k 的原理是 , 计算 a i , j 前面的元素个数 : k b e f o r e ( i , j ) = 3 ( i − 1 ) − 1 + j − ( i − 1 ) = 2 i + j − 3 计算k的原理是,计算a_{i,j}前面的元素个数:k_{before}(i,j)=3(i-1)-1+j-(i-1)=2i+j-3 计算k的原理是,计算ai,j前面的元素个数:kbefore(i,j)=3(i−1)−1+j−(i−1)=2i+j−3
-
B [ 0 , . . . , n − 1 ] , 从 B [ 0 ] 开始存放元素 a 0 , 0 , . . B[0,...,n-1],从B[0]开始存放元素a_{0,0},.. B[0,...,n−1],从B[0]开始存放元素a0,0,..
k 0 ( i , j ) = 3 ( i − 1 ) − 1 + j − ( i − 1 ) = 2 i + j − 3 k_0(i,j)=3(i-1)-1+j-(i-1)=2i+j-3 k0(i,j)=3(i−1)−1+j−(i−1)=2i+j−3
-
-
B [ 1 , . . . , n ] , 从 B [ 1 ] 开始存放元素 a 0 , 0 , . . . B[1,...,n],从B[1]开始存放元素a_{0,0},... B[1,...,n],从B[1]开始存放元素a0,0,...
这种情况也是有的(比如,我们用B[0]保存其他元信息,比如长度)
k 1 ( i , j ) = k 0 ( i , j ) + 1 = 2 i + j − 2 k_{1}(i,j)=k_{0}(i,j)+1=2i+j-2 k1(i,j)=k0(i,j)+1=2i+j−2
确定数组中的元素解压后的行/列公式
- 按行优先
确定行
i ( k ) = ⌊ k + 1 3 + 1 ⌋ = ⌊ k + 1 3 ⌋ + 1 = ⌊ k + 4 3 ⌋ i(k)=\lfloor{\frac{k+1}{3}+1}\rfloor=\lfloor{\frac{k+1}{3}}\rfloor+1 \\=\left\lfloor\frac{k+4}{3}\right\rfloor i(k)=⌊3k+1+1⌋=⌊3k+1⌋+1=⌊3k+4⌋
-
例如
- i ( 0 ) = 1 i ( 1 ) = 1 i ( 2 ) = 2 ⋮ i(0)=1 \\i(1)=1 \\i(2)=2 \\ \vdots i(0)=1i(1)=1i(2)=2⋮
我们来推导一下
i = 1 ; k = { ( − 1 ) ( 虚拟 ) 0 1 i = 2 ; k = { 2 3 4 i = 3 ; k = { 5 6 7 ⋮ i = i ; k = { 3 ( i − 1 ) − 1 3 ( i − 1 ) 3 ( i − 1 ) + 1 k + 1 = { 3 ( i − 1 ) 3 ( i − 1 ) + 1 3 ( i − 1 ) + 2 k + 1 3 = { ( i − 1 ) ( i − 1 ) + 1 3 ( i − 1 ) + 2 3 k + 1 3 + 1 = { i i + 1 3 i + 2 3 可见 : 上式子两边同时向下取整 , 就得到 k 映射到 i 的函数 ⌊ k + 1 3 + 1 ⌋ = ⌊ k + 1 3 ⌋ + 1 = i i ( k ) = ⌊ k + 1 3 + 1 ⌋ = ⌊ k + 1 3 ⌋ + 1 i=1;k=\begin{cases} (-1)(虚拟) \\0 \\1 \end{cases}\\ i=2;k=\begin{cases} 2 \\3 \\4 \end{cases}\\ i=3;k=\begin{cases} 5 \\6 \\7 \end{cases}\\ \vdots\\ i=i;k=\begin{cases} 3(i-1)-1 \\3(i-1) \\3(i-1)+1 \end{cases}\\ {k+1}=\begin{cases} 3(i-1) \\3(i-1)+1 \\3(i-1)+2 \end{cases}\\ \frac{k+1}{3}=\begin{cases} (i-1) \\(i-1)+\frac{1}{3} \\(i-1)+\frac{2}{3} \end{cases}\\ \frac{k+1}{3}+1=\begin{cases} i \\i+\frac{1}{3} \\i+\frac{2}{3} \end{cases}\\ 可见:上式子两边同时向下取整,就得到k映射到i的函数 \\ \lfloor{\frac{k+1}{3}+1}\rfloor=\lfloor{\frac{k+1}{3}}\rfloor+1 =i \\ i(k)=\lfloor{\frac{k+1}{3}+1}\rfloor=\lfloor{\frac{k+1}{3}}\rfloor+1 i=1;k=⎩ ⎨ ⎧(−1)(虚拟)01i=2;k=⎩ ⎨ ⎧234i=3;k=⎩ ⎨ ⎧567⋮i=i;k=⎩ ⎨ ⎧3(i−1)−13(i−1)3(i−1)+1k+1=⎩ ⎨ ⎧3(i−1)3(i−1)+13(i−1)+23k+1=⎩ ⎨ ⎧(i−1)(i−1)+31(i−1)+323k+1+1=⎩ ⎨ ⎧ii+31i+32可见:上式子两边同时向下取整,就得到k映射到i的函数⌊3k+1+1⌋=⌊3k+1⌋+1=ii(k)=⌊3k+1+1⌋=⌊3k+1⌋+1
确定列
- j ( k , i ) = k − 2 i + 3 ; 又因为 i = i ( k ) = ⌊ k + 1 3 + 1 ⌋ 或者 j ( k ) = j ( k , i ( k ) ) = k − 2 ( ⌊ k + 1 3 + 1 ⌋ ) + 3 j(k,i)=k-2i+3;又因为i=i(k)=\lfloor{\frac{k+1}{3}+1}\rfloor \\或者 \\j(k)=j(k,i(k))=k-2(\lfloor{\frac{k+1}{3}+1}\rfloor)+3 j(k,i)=k−2i+3;又因为i=i(k)=⌊3k+1+1⌋或者j(k)=j(k,i(k))=k−2(⌊3k+1+1⌋)+3
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了