求解!矩阵相乘的复杂度

wintelbailu 2009-04-20 07:55:32
一般的矩阵相乘算法matrix_self_multiply(...)(输入矩阵自相乘N=M*M,无需矩阵分块,只是简单的3重for循环的那种)的复杂度均认为是o(n^3)
而选择排序的算法sort(...)大家均认为是o(n^2)
如果我写一个函数
// 假设长度 n 为某个数的平方 n = t^2,以方便矩阵自相乘的运算条件
void test0(int[] array, size_t n)
{
sort(array, n); // 注意这里输入的数据的长度是 n = t^2

matrix_self_multiply(array, n); // 请注意这里函数的实现for 的范围是[1, t],关键的运算步骤是执行了 t^3 = n^1.5

}
的计算复杂度度少呢?o(n^2) 还是 o(n^3)?

如果是o(n^2),那么
void test1(int[] array, size_t n)
{
// sort(array, n);
matrix_self_multiply(array, n);
}
的复杂度是度少?还是o(n^2)?不是说矩阵相乘的复杂度是o(n^3)?
...全文
2928 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
Math_Room 2011-08-28
  • 打赏
  • 举报
回复
矩阵相乘的空间复杂度怎么算?
wintelbailu 2009-04-22
  • 打赏
  • 举报
回复
11楼的朋友,我曾经说过,我们大多数关心的是算法的平均计算复杂度或者是最坏复杂度。而且很多情况下我们更希望找到最坏复杂度小的解法。
当碰到类似以下test()函数时,我们如何分析它的复杂度,确切点说就是test()的最坏复杂度。
// suppose array.size = s * t
void test(int[] array, size_t s, size_t t)
{
f(array, s, t); // 某种已知平均计算复杂度和最坏计算复杂度均为O(n^2)

// some trivial steps can be neglected compared to f and matrix_self_multiply

matrix_self_multiply(array, s, t); // o(matrix_self_multiply = ?)

// other trivial steps can be neglected compared to f and matrix_self_multiply
}
// o(test) = ?

按你的建议我们在对test()中调用的矩阵相乘算法和某种计算复杂度为o(n^2)时排序算法用不同的衡量标准,似乎是不合适的。

谢谢你的回答
fire_woods 2009-04-22
  • 打赏
  • 举报
回复
楼主,当你用元素个数w(=s*t)无法准确描述算法时间复杂度的时候,就需要用更精细的变量来描述.
正如你所说的,当s和t变化的时候,矩阵乘法的时间复杂度是不一样的,那为什么不能直接用s和t来表达时间复杂度呢.
arong1234 2009-04-21
  • 打赏
  • 举报
回复
你题目关键的误导在于,你假定矩阵乘法可以先相乘,并且相乘以后复杂度可以降低非常大,而你这个假设是不成立的,因此得到了错误的结论
首先,矩阵乘法从来不是可以先排序再乘的,这是你对数学根本的误解
其次,自乘的复杂度还是n^3,而不是你说的(n/2)^3
在一系列荒谬的前提下推导出的结论,还是荒谬的
arong1234 2009-04-21
  • 打赏
  • 举报
回复
级联运算复杂度当然按大的算,怎么会是O(n^2)呢?当然是O(n^3)
考虑一个极限的情况,假如一个运算复杂度是O(1),另外一个复杂度是O(n^1000),先进行第一个计算,再进行第二个计算,随着n的增加,消耗的时间肯定是运算2的贡献大,而运算1逐渐被忽略
-布谷鸟- 2009-04-21
  • 打赏
  • 举报
回复
一堆数学大师在讨论问题!
  • 打赏
  • 举报
回复
矩阵相乘的复杂度是o(n^3)没错,但这里n的含义是矩阵的阶数,也就是说两个n*n矩阵相乘(换句话说,每个矩阵中实际上有n^2个元素)

而在你给出的test0()函数里,实际上n(=t^2)代表的是矩阵的元素个数。这两个“n”含义不一样,出来的复杂度分析结果当然不同!
wintelbailu 2009-04-21
  • 打赏
  • 举报
回复
我可能没有把问题说明白
首先,我写的test0()、test1()均是demo,并不适合某个要解决的实际问题,只不过是用来比较矩阵相乘的复杂度同选择排序算法的复杂度之间的大小关系,更确切的说是弄不清楚矩阵相乘算法的复杂度。
第二,在《算法导论 2ed》中第34章,34.1节中有这样的关于复杂度的介绍:
“我们把实例集为二进制的集合问题称为具体问题,如果当提供给一个算法的是长度为n=|i|的一个问题实例i时,算法可以在O(T(n))时间内长生问题的解,我们就说该算法在时间O(T(n))内解决了该具体问题.....”
我们注意到描述选择排序算法和矩阵相乘算法的编码长度都一样为n(因为输入的数据都一样),而对于排序算法只需要o(n^2)就可以得出结果,而矩阵相乘算法需要对矩阵的每一维进行运算,而这里每一维的长度均是t=n^0.5,所以总共的关键步骤的运算是O(t^3) = O(n^1.5),下面类c的伪代:

void matrix_self_multiply(int[] array, size_t n)
{
size_t t = square_root(n); // suppose n = t*t and t is an integer
int[] result;

for (int i = 1; i <= t; ++i)
{
for (int j = 1; j <= t; ++j)
{
result[i, j] = 0;
for (int k = 1; k <= t; ++k)
{
result[i, j] = result[i, j] + array[i, k] * array[k, j];
}
}
}
// 这里三重循环的迭代范围均为[1, t] = [1, n^0.5]

// other trivial steps
}


void test2(int[] array, size_t n)
{
int result = 0;

for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= n; ++j)
{
for (int k = 1; k <= n; ++k)
{
result += array[k];
}
}
}

// 这里三重循环的迭代范围是[1, n]

// other trivial steps
}

显然,test2()的计算复杂度是O(n^3),难道matrix_self_multiply()与test2()的计算复杂度是相等的吗?
wintelbailu 2009-04-21
  • 打赏
  • 举报
回复
7楼说“一维向量相乘,如果是(n*1)X(1*n)复杂度就是O(n*n),如果是(1*n)X(n*1)复杂度就是O(n)”
大多数情况下,我们关心的算法复杂度是最坏情况下的复杂度或者是平均计算复杂度
楼上说的情况只是极端的两个情况,但也方便去分析这样算法的复杂度

我们构造这样的一个算法,其功能就是将数组array按照指定的参数(s,t)构造N(s*t),M(t*s)的两个矩阵,并计算N*M的结果
// suppose array.size = s * t = w
void matrix_self_multiply_1(int[] array, size_t s, size_t t)
{
int[] result;

for (int i = 1; i <= s; ++i)
for (int j = 1; j <= s; ++j)
{
reuslt[i, j] = 0;
for (int k = 1; k <= t; ++k)
result[i, j] = result[i, j] + array[i, k] * array[k, j]
}

// other trivial steps
}

// suppose array.size = s * t = w
void test3(int[] array, size_t s, size_t t)
{
int w = s*t;
int result = 0;

for (int i = 1; i < w; ++i)
for (int j = 1; j < w; ++j)
result = result + array[j];

// other trivial steps
}

如果matrix_self_multiply_1中输入的数据个数是w,且有w=s*t,那么算法的复杂度按楼上定义是O(s*t*s)且有 s*t = w
我们可以方便的得到当s = w, t = 1时得到最大值为 w^2,
当s = 1, t = w时得到最小值w。

O(matrix_self_multiply_1)的平均计算复杂性在[o(w),o(w^2)]之间,且我们不论采用任何非一进制的编码方式描述该问题,设表述此问题的长度是n,显然n同w之间是有一个特定于编码方式的固定常数c,即n = cw, 故该问题的平均复杂度在[o(n), o(n^2)]之间,最坏复杂度为o(n^2),另外对于最坏复杂度的情况,可以注意到数组array的每一个元素都会被访问n次,且一共有n个这样的元素, 这种情况下与test3()有什么不同?也就是说此时矩阵相乘的算法的最坏复杂度也仅仅是o(n^2)?

再次感谢指教。
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 wintelbailu 的回复:]
按照楼上的定义,矩阵相乘运算的复杂度n是某一维的大小,这好像和计算复杂性的定义不符合吧。另外,假设输入的矩阵退化成一个列向量时,矩阵相乘的复杂度又是多大呢?
[/Quote]
具体问题ls已经回答过了。
如果你把矩阵相乘的复杂度定义成O(n^3),那n代表的肯定是n阶方阵。

复杂度说到底还是为了分析算法优劣,搞清楚这个最重要,倒不用一味拘泥于形式。
就像输入规模是n还是n^2有什么要紧吗?只是表达形式不同而已(况且任何分析都会指明n的含义),它的复杂度本身又不会发生变化。
一般说来,对于n阶方阵来说,人们还是习惯用n来作为输入规模,简单又好记。
fire_woods 2009-04-21
  • 打赏
  • 举报
回复
矩阵乘法m*k的矩阵X上k*n的矩阵,得到m*n的矩阵
复杂度是O(m*k*n)这么说楼主不知道能不能举一反三了呢?

顺便举例,一维向量相乘,如果是(n*1)X(1*n)复杂度就是O(n*n),如果是(1*n)X(n*1)复杂度就是O(n).
wintelbailu 2009-04-21
  • 打赏
  • 举报
回复

据我了解算法复杂度的o(n^k)中的n是表明的是输入数据的某种编码长度(非一进制编码),也就是输入问题的规模的度量,绝不是我在matrix_self_multiply(int[] array, size_t n)中的形参n,我完全可以重命名这个形参为length
注意到matrix_self_multiply算法以及sort()算法的输入问题规模均可以认为n,算法复杂度是以问题的规模来度量的,绝不是函数的形参所能表达的。

引《计算理论导引 2ed》第七章 时间复杂性
有如下定义:
定义7.1 令M是一个在所有输入上都停机的确定性图灵机。M的运行时间或者时间复杂度,是一个函数f:N->N,其中N是非负整数集合,f(n)是M在所有长度为n的输入上运行时所经过的最大步骤。若f(n)是M的运行时间,则称M在时间f(n)内运行,M是f(n)时间图灵机。通常使用n表示输入的长度。

按照楼上的定义,矩阵相乘运算的复杂度n是某一维的大小,这好像和计算复杂性的定义不符合吧。另外,假设输入的矩阵退化成一个列向量时,矩阵相乘的复杂度又是多大呢?
谢谢赐教!
ericming200409 2009-04-20
  • 打赏
  • 举报
回复
楼主另发贴加分吧 这么吝啬

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧