矩阵行列式求法

矩阵的行列式求法

    • 拉普拉斯展开
    • 交错和
    • 想办法变成上三角矩阵
        • 经典高斯消元法
        • LU分解

行列式求法很多,下面是比较常见的几种。矩阵A的行列式记成 d e t ( A ) det(A) det(A).

拉普拉斯展开

根据行列式的代数余子式定义,矩阵按某行或某列展开: det ⁡ ( A ) = ∑ j = 1 n ( − 1 ) i + j a i j det ⁡ ( A i j ) = ∑ i = 1 n ( − 1 ) i + j a i j det ⁡ ( A i j ) \operatorname{det}(A)=\sum_{j=1}^{n}(-1)^{i+j} a_{i j} \operatorname{det}\left(A_{i j}\right)=\sum_{i=1}^{n}(-1)^{i+j} a_{i j} \operatorname{det}\left(A_{i j}\right) det(A)=j=1n(1)i+jaijdet(Aij)=i=1n(1)i+jaijdet(Aij)
这个直接递归就能搞定,时间复杂度: T ( n ) = T ( n − 1 ) n + n T(n)=T(n-1)n+n T(n)=T(n1)n+n
这个复杂度迭代计算得到: T ( n ) = ∑ i = 0 n − 1 n ! i ! = O ( n ∗ n ! ) T(n)=\sum_{i=0}^{n-1}\frac{n!}{i!}=O(n*n!) T(n)=i=0n1i!n!=O(nn!)
复杂度过于骇人听闻,所以实际没人敢用。只适用于一些线性代数考试题。
核心代码:

int det_matrix(Matrix& mat, int row)
{
    if(row == 2)
    {
        double* arr = mat.get_mat();
        return arr[0 * row + 0] * arr[1 * row + 1] - arr[0 * row + 1] * arr[1 * row + 0];
    }
    else
    {
        double res = 0;
        double *vec = mat.get_mat();
        for(int i = 0; i < row; i++)
        {
            int k = 1;
            if(i % 2 == 1)
            {
                k = -1;
            }
            Matrix new_mat = remove_row_col(mat,1, i + 1);
            res += vec[i] * k * det(new_mat,row - 1);   
        }
        return res;
    }
}

交错和

这种方法是生成一个1-n的排列p,然后按这个排列选数累乘,按排列的逆序对数决定符号。显然一共n!项,每项连乘O(n),复杂度还是O(n*n!)。连线性代数考试都不屑于用。

想办法变成上三角矩阵

上三角矩阵的行列式是主对角线元素的连乘,可以按第一列做拉普拉斯展开,数学归纳法证明。

经典高斯消元法

用第三类初等行变换把矩阵变成上三角阵,这样行列式是不变的。第三类初等行变换是把某行的k倍加到别的行上去。这个实际上是高斯消元。

LU分解

这个本质上还是高斯消元。因为把初等变换施加到单位矩阵E上,可以记录下变换操作。将原矩阵左乘这个记录矩阵就相当于对原矩阵做了初等行变换。这里大概描述LU分解的原理:
一个可逆矩阵A一定可以分解成 A = L ∗ U A=L*U A=LU
U是和A等价的上三角矩阵。
L是一个下三角矩阵,对主角线一定都是1,L与A向U变换的操作步骤有关。
很明显L和U的求法可以高斯消元,也可以直接求。具体另一篇博客会解释。

你可能感兴趣的:(矩阵,算法)