算法设计与分析(上)
算法复杂度整理
O(f(n))的大小关系
l o g l o g n < l o g n < ( l o g n ) 2 < n < n < n l o g n < n 1 + ϵ < n 2 < n 3 < 2 n − 1 = 2 n < e n < n ! < n n loglogn<logn<(logn)^2<\sqrt{n}<n<nlogn<n^{1+\epsilon}<n^2<n^3<2^{n-1}=2^n<e^n<n!<n^n loglogn<logn<(logn)2<n<n<nlogn<n1+ϵ<n2<n3<2n−1=2n<en<n!<nn
O(n)
- PK算法:名人问题,常见元素问题取k=2
- 单调栈: 左边第一大问题,观景房问题
- 大小镜面算法:颠倒词序问题
- 极值保持算法: 最大连续和子串
- partition
- merge
公式整理
平滑曲线: ∀ n , f ( 2 n ) ∈ θ ( f ( n ) ) \forall n, f(2n)\in\theta(f(n)) ∀n,f(2n)∈θ(f(n))
- 不是平滑曲线的有: 2 n , n ! 2^n, n! 2n,n!
- 相关定理:为方便证明复杂度,可设题给输入为 2 n 2^n 2n,若结果为 O ( f ( n ) ) O(f(n)) O(f(n))&& f ( n ) f(n) f(n)为平滑曲线,那么结果正确,否则不能设输入规模为 2 n 2^n 2n
数列相关公式
- 等比数列:
- ∑ i = 1 n a q i = a ( q n + 1 − 1 q − 1 ) \sum_{i=1}^n aq^i=a(\frac{q^{n+1}-1}{q-1}) ∑i=1naqi=a(q−1qn+1−1)
- 在 O ( f ( n ) ) O(f(n)) O(f(n))的意义下,若 q > 1 q\gt1 q>1则只取最后一项,若 q < 1 q\lt1 q<1则只取第一项
- ∑ i = 1 n i = \sum_{i=1}^n i= ∑i=1ni= n ( n + 1 ) 2 n(n+1)\over2 2n(n+1)
- ∑ i = 1 n i 2 = \sum_{i=1}^n i^2= ∑i=1ni2= Θ ( 1 3 n 3 ) \Theta(\frac{1}{3}n^3) Θ(31n3)
- ∑ i = 1 n i k = \sum_{i=1}^n i^k= ∑i=1nik= Θ ( 1 k + 1 n k + 1 ) \Theta(\frac{1}{k+1}n^{k+1}) Θ(k+11nk+1)
- ∑ i = 1 n i ∗ 2 i = \sum_{i=1}^n i*2^i= ∑i=1ni∗2i= ( n − 1 ) 2 n + 1 + 2 (n-1)2^{n+1}+2 (n−1)2n+1+2
- ∑ i = 1 n 1 i = \sum_{i=1}^n \frac{1}{i}= ∑i=1ni1= l n n + 1 2 n ≈ O ( l o g n ) lnn+\frac{1}{2n}\approx \Omicron(logn) lnn+2n1≈O(logn)
渐进符号公式
- f ( n ) = ο ( g ( n ) )    i f f    lim n → ∞ f ( n ) g ( n ) = 0 f(n)=\omicron (g(n))\;iff\;\lim_{n\to\infty}\frac{f(n)}{g(n)}=0 f(n)=ο(g(n))ifflimn→∞g(n)f(n)=0
- f ( n ) = O ( g ( n ) )    i f f    lim n → ∞ f ( n ) g ( n ) = c < ∞ f(n)=\Omicron (g(n))\;iff\;\lim_{n\to\infty}\frac{f(n)}{g(n)}=c<\infty f(n)=O(g(n))ifflimn→∞g(n)f(n)=c<∞
- f ( n ) = Θ ( g ( n ) )    i f f    lim n → ∞ f ( n ) g ( n ) = c    ( 0 < c < ∞ ) f(n)=\Theta (g(n))\;iff\;\lim_{n\to\infty}\frac{f(n)}{g(n)}=c\;(0<c<\infty) f(n)=Θ(g(n))ifflimn→∞g(n)f(n)=c(0<c<∞)
- f ( n ) = Ω ( g ( n ) )    i f f    lim n → ∞ f ( n ) g ( n ) = c    ( c > 0 ) f(n)=\Omega (g(n))\;iff\;\lim_{n\to\infty}\frac{f(n)}{g(n)}=c\;(c>0) f(n)=Ω(g(n))ifflimn→∞g(n)f(n)=c(c>0)
- f ( n ) = ω ( g ( n ) )    i f f    lim n → ∞ f ( n ) g ( n ) = ∞ f(n)=\omega (g(n))\;iff\;\lim_{n\to\infty}\frac{f(n)}{g(n)}=\infty f(n)=ω(g(n))ifflimn→∞g(n)f(n)=∞
Master定理 T ( n ) = a T ( n b ) + f ( n ) T(n)=aT(\frac{n}{b})+f(n) T(n)=aT(bn)+f(n)
- 若 f ( n ) ∈ O ( n l o g b a − ϵ ) , 则 T ( n ) = Θ ( n l o g b a ) f(n)\in \Omicron (n^{log_{b}^a-\epsilon}),则T(n)=\Theta(n^{log_{b}^a}) f(n)∈O(nlogba−ϵ),则T(n)=Θ(nlogba)
- 若 f ( n ) ∈ Ω ( n l o g b a + ϵ ) , 且 f ( n ) 平 滑 , 则 T ( n ) = θ ( f ( n ) ) f(n)\in \Omega (n^{log_{b}^a+\epsilon}),且f(n)平滑,则T(n)=\theta(f(n)) f(n)∈Ω(nlogba+ϵ),且f(n)平滑,则T(n)=θ(f(n))
- 若 f ( n ) ∈ Θ ( n l o g b a + ϵ ) , 则 T ( n ) = θ ( n l o g b a l o g n ) f(n)\in \Theta (n^{log_{b}^a+\epsilon}),则T(n)=\theta(n^{log_{b}^a}logn) f(n)∈Θ(nlogba+ϵ),则T(n)=θ(nlogbalogn)
- 巧计:大于大的,小于小的,相等乘以树高, f ( n ) f(n) f(n)对等比数列的影响不能太大,需要平滑
加强版Master定理:
- 适用于 T ( n ) = ∑ i k a i T ( n / b i ) + f ( n ) T(n)=\sum_{i}^k {a_{i}T(n/b_{i})}+f(n) T(n)=∑ikaiT(n/bi)+f(n)
- 此时 n n n的幂次 p p p,是方程 ∑ i k a i b i − p = 1 \sum_{i}^k a_{i}b_{i}^{-p}=1 ∑ikaibi−p=1的解
- 其余的与MASTER定理一样
算法下界证明
决策树
典型算法实现
partition
以a[l]为pivot的经典版本
int partition(int *a, int l,int r)
{
int key=a[l];
int smallpos=l+1;
int temp;
for(int i=l+1;i<=r;i++)
if(a[i]<key)
swap(a[i],a[smallpos++]);
smallpos-=1;
swap(a[smallpos],a[l]);
return smallpos;
}
连续和子串
循环维持的是a1+a2+...+ak<0中的ak一定是第一次让字串小于0的k
这个性质,由此可以推导出:
a
j
+
1
+
a
j
+
2
+
.
.
.
+
a
k
<
0
→
a_{j+1}+a_{j+2}+...+a_{k}<0\rightarrow
aj+1+aj+2+...+ak<0→
a
j
+
1
+
a
j
+
2
+
.
.
.
+
a
k
+
a
k
+
1
<
a
k
+
1
a_{j+1}+a_{j+2}+...+a_{k}+a_{k+1}<a_{k+1}
aj+1+aj+2+...+ak+ak+1<ak+1恒成立
sum := 0;
max := a[0];
for i := 0 to n:
sum += a[i];
if( sum > max ):
max := sum;
else if(sum < 0):
sum := 0;
MergeSort
将两个有序数组用 O ( n ) \Omicron(n) O(n)时间排成一个有序数组
void MergeSort(int l, int r) {
if (l >= r)return;
int mid = (l + r) / 2;
merge(l, mid);
merge(mid + 1, r);
for (int i = l; i <= mid; i++)
t[i] = a[i];
for (int i = r, j = mid + 1; i >= mid + 1; i--, j++)
t[j] = a[i];
int current = l;
while (l <= r)
{
if (t[l] <= t[r])
{
a[current++] = t[l];
l++;
}
else
{
a[current++] = t[r];
r--;
ans += mid - l + 1;//是为了逆序对问题,可不加
}
}
}
例题
递归方程的解法:
- 解法一:猜证法
-
T
(
n
)
=
2
(
T
(
n
/
2
)
)
+
n
T(n)=2(T(n/2))+n
T(n)=2(T(n/2))+n
- guess that T ( n ) ∈ O ( n l o g n ) T(n)\in O(nlogn) T(n)∈O(nlogn)
- then should prove : ∃ c , ∀ n T ( n ) ≤ c n l o g n \exist c,\forall n T(n) \leq cnlogn ∃c,∀nT(n)≤cnlogn
-
T
(
n
)
=
2
(
T
(
n
2
)
)
+
n
T(n) = 2(T(\frac {n}{2})) + n
T(n)=2(T(2n))+n
≤ 2 ∗ ( c n 2 l o g n 2 ) + n \leq2*(c \frac {n}{2} log\frac{n}{2})+n ≤2∗(c2nlog2n)+n
= c n l o g n − c n + n =cnlogn-cn+n =cnlogn−cn+n
= c n l o g n + n ( 1 − c ) =cnlogn +n(1-c) =cnlogn+n(1−c)
≤ c n l o g n    ( c ≥ 1 ) \leq cnlogn\; (c\ge 1) ≤cnlogn(c≥1)
-
T
(
n
)
=
T
(
n
)
+
1
T(n)=T(\sqrt{n})+1
T(n)=T(n)+1
- x → 2    \sqrt{x}\rightarrow2\; x→2需要 l o g l o g x loglogx loglogx次操作
- 然后列方程证即可
未完待续…