什么是杨辉三角:
特点:
1、每个数字等于上一行的左右两个数字之和。
2、第n+1行的第i个数等于第n行的第i-1个数和第i个数之和,即 C(n+1,i)=C(n,i)+C(n,i-1)。
下面我们通过两种不同的办法实现杨辉三角:
初阶:
步骤一:利用循环在二维数组中填充一个杨辉三角雏形
for (i = 0; i < row; i++) { for (j = 0; j <= i; j++) { arr[i][j] = 1; } }
令 j<=i 而不是row,是因为我们只要一半的三角形,j会因i的大小(行数大小)发生改变而与其始终保持一致。
如果令 j<=row 填充的实际上就是一个正方形
步骤二:利用特点实现内部数字的相加
for (i = 1; i < row; i++) { for (j = 1; j <= i; j++) { arr[i + 1][j] = arr[i][j] + arr[i][j - 1]; } }
令i = 1,j =1 是为了从杨辉三角第三行的第二个数字开始打印,因为第一二行全为1且每一行第一个数字也为1。
例:
当i = 1时,arr[2][1] = arr[1][1] + arr[1][0]; 当i = 2时,arr[3][1] = arr[2][1] + arr[2][0]、arr[3][2] = arr[2][2] + arr[2][1];
步骤三:遍历打印数组的同时使杨辉三角成型
for (i = 0; i < row; i++) { for (j = 0; j <= i; j++) { printf("%d ", arr[i][j]); } }
这里与步骤一基本相似,只是将填充换成了打印的功能。
!!!注意 !!!
打印与填充的循环结构最好一致,如果填充时填充成正方形,打印时仍与步骤三一样那么打印结果看起来仍然是正确的,但其实数组里面的实际情况是这样的:
如果填充时填充了一半,但是打印时又变成了打印全部,就会出现这样的情况:
所以,一定要注意打印与填充两个函数的书写,内部数字的加减其实还会更简单点
小拓展:
以上操作只是打印出一个有杨辉三角的内容但是没有杨辉三角形状的三角形。下面我们学习如何实现真正意义上的杨辉三角。
具体操作:在打印每一行数字之前先打印足够多的 "空格" 。
代码如下:
for (int k = 0; k <row - i; k++) { printf(" "); //这里输入三个空格 }
令 k<row-i 的原因是:随着i的增加每次要打印的空格数组数不断减少,即k的循环次数不断减少。
同时对于打印代码也要做一定调整:
for (j = 0; j <=i; j++) { printf("%5d ", arr[i][j]); }
至于为什么时 "%5d" ,一个一个试出来的呗┭┮﹏┭┮
整体实现代码:
#include <stdio.h> int print(int arr[9][9], int row) { int i, j; //打印一个全是1的杨辉三角雏形 for (i = 0; i < row; i++) { for (j = 0; j <=i; j++) { arr[i][j] = 1; } } //实现内部空间数的加法 for (i = 1; i < row; i++) { for (j = 1; j <= i; j++) { arr[i + 1][j] = arr[i][j] + arr[i][j - 1]; } } //循环打印数组 for (i = 0; i < row; i++) { for (int k = 0; k <row - i; k++) { printf(" "); } for (j = 0; j <=i; j++) { printf("%5d ", arr[i][j]); } printf("\n"); } } int main() { int arr[9][9]; //定义一个二维数组 print(arr, 9); return 0; }
进阶:
方法一的空间复杂度为n^2,方法二的代码可以降低整体代码的空间复杂度至n。
步骤一:
我们抛弃之前的打印填充数组的办法改用直接定义一个全为1的整型数组,同时直接将第一行打印出来。
int data[30] = { 1 };
步骤二:
由于我们在填第n行的杨辉三角时,只跟第n-1行的杨辉三角产生联系,不会跟之前的有联系,所以没必要保存每一行的杨辉三角,填一行打一行就行了。
for (i = 1; i < n; i++) //从第二行开始 { for (j = i; j > 0; j--) //从后向前填,避免上一行的数据在使用前就被覆盖 { data[j] += data[j - 1]; //公式同上,由于变成了一维,公式也变简单了。 } for (int k = 0; k < n - i; k++) { printf(" "); } for (j = 0; j <= i; j++) //这一行填完就直接打印了。 { printf("%5d ", data[j]); } putchar('\n'); }
整体实现代码:
#include <stdio.h> void yangHuiTriangle(int n) { int data[30] = { 1 }; int i, j; for (i = 0; i < n; i++) //从第二行开始 { for (j = i; j > 0; j--) //从后向前填,避免上一行的数据在使用前就被覆盖 { data[j] += data[j - 1]; //公式同上,由于变成了一维,公式也变简单了。 } for (int k = 0; k < n - i; k++) { printf(" "); } for (j = 0; j <= i; j++) //这一行填完就直接打印了。 { printf("%5d ", data[j]); } putchar('\n'); } } int main() { int n = 0; printf("请输入要打印的行数:"); scanf_s("%d", &n); yangHuiTriangle(n); return 0; }