上下限理论提供了一种找到最低复杂度算法来解决问题的方法。在理解该理论之前,首先让我们简要了解一下下界和上限。
- 下界–
假设L(n)是算法A(say)的运行时间,则g(n)是A的下界,如果存在两个常数C和N,使得L(n)> = C * g(n)当n> N时。算法的下界由称为Big Omega(或仅Omega)的渐近符号表示。 - 上界–
假设U(n)是算法A(say)的运行时间,则g(n)是A的上限,如果存在两个常数C和N,使得U(n)<= C * g(n)当n> N时。算法的上限由称为Big Oh(O)(或简称Oh)的渐近符号表示。
1.下界理论:
根据下限理论,对于算法的下限L(n),对于随机输入,不可能有其他算法(对于常见问题)的时间复杂度小于L(n)。同样,在最坏的情况下,每个算法都必须至少花费L(n)时间。请注意,此处的L(n)是所有可能算法中的最小值,具有最大的复杂度。
下界对于任何算法都是非常重要的。一旦计算完,就可以将其与算法的实际复杂度进行比较,如果它们的顺序相同,则可以将算法声明为最佳算法。因此,在本节中,我们将讨论有关找到算法下限的技术。
请注意,我们的主要动机是获得一种最佳算法,该算法的上限与下限相同(U(n)= L(n))。合并排序是最佳算法的常见示例。
琐碎的下界–
这是找到下限的最简单方法。根据获取的输入数量和输出产生的数量可以轻松观察到的下限称为平凡下限。
示例: nxn矩阵相乘,其中,
Input: For 2 matrix we will have 2n2 inputs
Output: 1 matrix of order n x n, i.e., n2 outputs
在上面的示例中,它的下界很容易预测为O(n 2 )。
计算模型–
该方法适用于所有基于比较的算法。例如,在排序中,我们必须比较列表中的元素,然后对它们进行相应的排序。搜索的情况与此类似,因此我们可以在这种情况下实现相同的功能。现在,我们将看一些示例以了解其用法。
有序搜索–
这是一种搜索,其中列表已被排序。
示例1:线性搜索
解释 –
在线性搜索中,如果键不匹配,则将键与第一个元素进行比较,然后将其与第二个元素进行比较,依此类推,直到对第n个元素进行检查。否则,我们将以失败告终。
示例2:二进制搜索
解释 –
在二进制搜索中,我们对照键检查中间元素,如果更大,我们搜索前一半,否则我们检查后一半并重复相同的过程。
下图说明了由4个元素组成的数组中的二进制搜索
计算下限:比较的最大数量为n。让树中有k个等级。
- 节点数为2 k -1
- 在大小为n的列表的元素的任何基于比较的搜索中,没有节点的上限将为n,因为在最坏的情况下2 k -1最多有n个比较
- 每个级别将进行1次比较,因此没有。比较数k≥| log 2 n |
因此,从n个元素的列表进行的任何基于比较的搜索的下限不能小于log(n)。因此,可以说二进制搜索是最优的,因为其复杂度为Θ(log n)。
排序–
下图是通过3个元素的排序组合形成的树的示例。
示例–对于n个元素,使用计算模型查找下界。
解释 –
对于n个元素,我们总共有n个!组合(叶节点)。 (请参阅该图,其总组合为3!或6)也很明显,所形成的树是二叉树。图中的每个级别都表示一个比较。让那里为k水平=> 2 k在满二叉树在这种情况下,我们有N个叶节点总数从而!≤2ķ。
由于以上示例中的k是比较数,因此通过计算模型下键= k。
Now we can say that,
n!≤2T(n)
Thus,
T(n)>|log n!|
=> n!<=nn
Thus,
log n!<=log nn
Taking ceiling function on both sides, we get
|-log nn-|>=|-log n!-|
Thus complexity becomes Θ(lognn) or Θ(nlogn)
使用下键理论解决代数问题:
- 直线计划–
没有任何循环或控制结构的程序类型称为“直线程序”。例如,
C
//summing to nos
Sum(a, b)
{
//no loops and no control structures
c:= a+b;
return c;
}
C
Algo_Sol(a, b, c, x)
{
//1 assignment
v:=a*x;
//1 assignment
v:=v+b;
//1 assignment
v:=v*x;
//1 assignment
ans:=v+c;
return ans;
}
C
pow(x, n)
{
p := 1;
//loop from 1 to n
for i:=1 to n
p := p*x;
return p;
}
polynomial(A, x, n)
{
int p, v:=0;
for i := 0 to n
//loop within a loop from 0 to n
v := v + A[i]*pow(x, i);
return v;
}
C
polynomial(A, x, n)
{
int p, v=0;
// loop executed n times
for i = n to 0
v = (v + A[i])*x;
return v;
}
- 代数问题–
与代数有关的问题,例如求解方程不等式等,都属于代数问题。例如,使用简单的编程来求解方程ax 2 + bx + c。
C
Algo_Sol(a, b, c, x)
{
//1 assignment
v:=a*x;
//1 assignment
v:=v+b;
//1 assignment
v:=v*x;
//1 assignment
ans:=v+c;
return ans;
}
在这里求解的复杂度为4(不包括返回值)。
上面的示例向我们展示了一种求解2次多项式方程的简单方法,即4,因此对于n次多项式,我们将具有O(n 2 )的复杂度。
让我们通过一个算法进行演示。
例如: a n x n + a n-1 x n-1 + a n-2 x n-2 +…+ a 1 x + a 0是阶数n的多项式。
C
pow(x, n)
{
p := 1;
//loop from 1 to n
for i:=1 to n
p := p*x;
return p;
}
polynomial(A, x, n)
{
int p, v:=0;
for i := 0 to n
//loop within a loop from 0 to n
v := v + A[i]*pow(x, i);
return v;
}
循环内循环=>复杂度= O(n 2 );
现在要找到最佳算法,我们需要在此处找到下限(根据下限理论)。根据下界理论,解决上述问题的最佳算法是具有复杂度O(n)的算法。让我们用下界证明这个定理。
定理:证明求解多项式的最佳算法为O(n)
证明:减少算法的最佳解决方案是通过将多项式划分为几个直线问题来使此问题变得不太复杂。
=> anxn+an-1xn-1+an-2xn-2+...+a1x+a0
can be written as,
((..(anx+an-1)x+..+a2)x+a1)x+a0
Now, algorithm will be as,
v=0
v=v+an
v=v*x
v=v+an-1
v=v*x
...
v=v+a1
v=v*x
v=v+a0
C
polynomial(A, x, n)
{
int p, v=0;
// loop executed n times
for i = n to 0
v = (v + A[i])*x;
return v;
}
显然,此代码的复杂度为O(n)。这种求解这类方程的方法称为霍纳法。下界理论在这里起作用,并给出最佳算法的复杂度为O(n)。
2.上限理论:
根据上限理论,对于一个算法的上限U(n),我们总是可以在最多U(n)的时间内解决问题。已知算法解决输入情况较差的问题所花费的时间使我们上限。