掌握矩阵的行列式知识可以应对多种与之相关的程序题:
程序题1:写程序求如下方程组的解 =》克莱姆法则
程序题2:给定一个N×N的矩阵A,求|A|。=》矩阵的行列式值
程序题3:写程序求1,5,3,9,7的逆序数 =》行列式展开
数学1会从空间角度去分析线性代数,由向量到矩阵再到行列式,是最科学最全面的学习路线,因为越是难的科目越是需要你自身站的高度足够高,能高到站在大气层俯视才好,但在数学2+物理中,线性代数的分值毕竟只有十几分,我们就尽量的简略一下,把一切都以线性方程组求解为目的,以便能将更多的精力花费在大学物理的学习中。
线性方程组的解有下列三种情况:
1、无解 在直角坐标系中二者平行
系数矩阵 ,主对角线相乘和斜对角线再相减为0,如下:
2、有唯一解 在直角坐标系中二者相交于点(1.5,-0.5)
系数矩阵,主对角线相乘和斜对角线再相减不为0,如下:
3、有无穷对个解 在直角坐标系中二者重合
系数矩阵 ,主对角线相乘和斜对角线再相减为0,如下:
可见,对于2X2非齐次线性方程,方程系数的二阶矩阵的主对角线乘积和斜对角乘积相减的结果不为0的情况下,方程才会有唯一解。这个结果就是矩阵的行列式值。
一、行列式定义
行列式在数学中,是一个函数,其定义域为det的矩阵A,取值为一个标量,写作det(A)或 | A | 。
如
1)二阶行列式
,主对角线相乘-副对角线相乘
程序题:写代码求2阶行列式的值
int a[2][2];
printf("请你输入2阶行列式\n");
for (int i = 0; i < 2; i++)
{
for(int j = 0; j < 2; j++)
{
scanf_s("%d", &a[i][j]);
}
}
printf("行列式如下:\n");
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
printf("%d", a[i][j]);
printf("%s", " ");
if (j == 1) {
printf("%s", "\n");
}
}
}
int result = a[0][0] * a[1][1] - a[0][1] * a[1][0];
printf("行列式的值:%d",result);
运行结果:
2)三阶行列式
通过构建3X6阶矩阵划线法,得到公式。
程序题:写代码求3阶行列式的值
int a[3][3];
printf("请你输入3阶行列式\n");
for (int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
scanf_s("%d", &a[i][j]);
}
}
printf("行列式如下:\n");
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d", a[i][j]);
printf("%s", " ");
if (j == 2) {
printf("%s", "\n");
}
}
}
int result = a[0][0] * a[1][1]*a[2][2] + a[0][1] * a[1][2]*a[2][0]+ a[0][2] * a[1][0] * a[2][1]
- a[0][0] * a[1][2] * a[2][1]- a[0][1] * a[1][0] * a[2][2]- a[0][2] * a[1][1] * a[2][0];
printf("行列式的值:%d",result);
运行结果:
2)n阶行列式
n阶行列式等于所有取自不同行不同列的n个元素的乘积的代数和,逆序数为偶数时带正号,逆序数为奇数时带负号,共有n!项。
n阶行列式的定义中出现了逆序数的概念,用来确定乘积代数和的符号。
逆序数:在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数, 那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。逆序数为偶数的排列称为偶排列;逆序数为奇数的排列称为奇排列。
例如在序列 { 2, 4, 3, 1 } 中,逆序依次为 (2,1),(4,3),(4,1),(3,1),因此该序列的逆序数为 4,是偶排列。
当n=2时,共有2!=2项,即主副对角线乘积的代数和,且主对角线方向为正,副对角线方向为负。
当n=3时,共有3!=6项,通过构建3X6阶矩阵划线法,刚好可以得到这6项乘积,且主对角线方向为正,副对角线方向为负。
当n>3时,共有n!项,通过构建nX2n阶矩阵已无法满足定理,比如n=4时,共有4!=24项,而通过构建nX2n阶矩阵只能得到8项乘积的代数和。
程序题:写代码求n阶行列式的值
现在,根据手头上掌握的知识,我们只能根据n阶行列式的定义来解决这个问题了:
1)第一步需要一个获取n!项所有取自不同行不同列的n个元素的算法,即求1到n的全排列。
2)第二步需要一个获取每项的逆序数的算法(归并排序或者树状数组),逆序数为偶数时带正号,逆序数为奇数时带负号
3)第三步计算全排列乘积的代数和
上面的思路是根据n阶行列式的定义来求解的,正确的解决了n阶行列式求值的问题 ,但毕竟同时涉及了查找与排序,这会导致最终它的算法复杂度必然是非常高的。对比之前我们解决2阶或者3阶行列式时用的划线法就不存在算法复杂度的问题。
算法复杂度是指算法在编写成可执行程序后,运行时所需要的资源,资源包括时间资源和内存资源。
程序题:求1,2,3...,n的和。
int result=0; for(int i=1;i<=n;i++) { result+=i; }
🤮🤮🤮🤮🤮_____________________________________________________________________
解:n*(n+1)/2,这在大街上随便问一个人,他想都不想就能给你正确答案,同时也是这道题的唯一答案,这个答案很巧妙,它并不涉及时间复杂度,也不涉及空间复杂度,而只与cpu有关,是最优解。这本就是一道初中数学的问题,就要用初中数学的知识来解答。试想一下,如果这道题你回答了一个和大众完全不同的答案,你要如何来证明自己真的上过初中?这对于公务员类考试来说是非常可怕的事,可怕到啥程度呢,就用下面这道题打个比方吧:
翻译题,将下面这句话分别用不同语言翻译一下
求1,2,3...,n的和。
英语:
Finding the sum of 1,2,3,... N
法语:
Trouver la somme de 1, 2, 3..., n
c语言:
int result=0;
for(int i=1;i<=n;i++)
{
result+=i;
}———————————————————————————————
瞧,你真的只是把题目翻译了一下。
书接上文,现阶段,根据手头上掌握的知识,要求n阶行列式的值,我们只能根据n阶行列式的定义来做,这就相当于只是单纯的做了一下翻译工作,白框中的内容危言耸听了,因为这个翻译工作通长是解决问题中必要的一步,因为一旦我们设计出了很好的方法去解决求n阶行列式的值,需要通过n阶行列式的定义去验证,测试准确性。
总结:n个数的全排列,n个数的逆序数,归并排序等经典问题都是从n阶行列式的定义引导出来的,其作用也是考察你对n阶行列式的定义的理解。算法题大体都是这样有出处的。