#958. [基础]数组II

[基础]数组II

No testdata at current.

No submission language available for this problem.

二维数组

那么二维数组则多个一维数组,按下标有序性集合到一起

图示为 4*4 的二维数组,可以称为 4*4 的矩阵,4*4 的方阵

假设存入的数组 int a[4][4];

image

以 4*4 二维数组为例,需要熟知:
a[0] 是第 1 个一维数组
a[1] 是第 2 个一维数组
a[2] 是第 3 个一维数组
a[3] 是第 4 个一维数组
综上,a[i] 是第 i + 1 个数组

a[0][0] 表示第 1 个一维数组的第一个元素,即二维数组的第一个元素

a[0][3] 表示第 1 个一维数组的最后一个元素,即二维数组的第一行最后一个元素

a[3][0] 表示最后一个 (第 4 个) 一维数组的的第一个元素,即二维数组的最后一行的第一个元素

a[3][3] 表示最后一个 (第 4 个) 一维数组的最后一个元素,即二维数组的最后一行的最后一个元素。

二维数组的定义

以整数为例定义一个 n 行 m 列的二维数组:int a[n][m];

一般解题时,数组的构建需要考虑其最大范围。

需要构建一个 n*m 的 int 类型的二维数组,1 <= n, m <= 100

为了满足最大尺寸的需要,数组定义应当至少

int a[100][100];

考虑到一些代码习惯和共识用法,一般数组都会开得略大些,即

int a[105][105]; // 开大一点是个好习惯

二维数组的输入与输出

构建一个 n*m 的 int 类型的二维数组,1 <= n, m <= 100,并输入 n*m 个整数,且按 n 行 m 列输出

输入格式

第 1 行 2 个整数 n m

第 2 行开始的 n 行,每行 m 个整数

输出格式

n 行 m 列的整数阵列

3 4
1 2 3 4
4 3 2 1
0 9 8 7
1 2 3 4
4 3 2 1
0 9 8 7
样例代码
#include <iostream>
using namespace std;

const int N = 110;
int a[N][N];
int n, m;

int main () {
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) {
        for (int j = 1; j <= m; j ++) {
            cin >> a[i][j];
        }
    }

    for (int i = 1; i <= n; i ++) {
        for (int j = 1; j <= m; j ++) {
            cout << a[i][j] << ' ';
        }  
        cout << endl;
    }
    return 0;
}

提示

二维数组的输入输出,本质是利用二重循环对下标的遍历

for (int i = 1; i <= n; i ++) {
    for (int j = 1; j <= m; j ++) {
           /*  i 和 j  */
    } 
}

代码解读

当 i 为 1 时,j 从 1 遍历到 m , 内循环结束,i ++ 变成 2, i <= n 为真继续

当 i 为 2 时,j 从 1 遍历到 m , 内循环结束,i ++ 变成 3, i <= n 为真继续

当 i 为 3 时,j 从 1 遍历到 m , 内循环结束,i ++ 变成 4, i <= n 为真继续
...
当 i 为 n 时,j 从 1 遍历到 m,内循环结束,i ++ 变成 n+1, i <= n 为假退出

综上,(i, j) 组合是:

(1, 1) (1, 2) (1, 3) ... (1, m)
(2, 1) (2, 2) (2, 3) ... (2, m)
...                  ...   ...
(n, 1) (n, 2) (n, 3) ... (n, m)

即下标的变化都有,即 a[i][j] 从左往右,从上往下都能遍历到。

示例用法

核心思想:数组的核心要素是下标。(适用于所有维度的数组)

一般问题都可以归纳为:下标与值的关系,下标变化的规律。

针对一个已输入的二维数组 a

注意,这里代码是从 (1,1) 到 (n,m) 的二维数组

int n, m, a[110][110];
cin >> n >> m;
for (int i = 1; i <= n; i ++) {
    for (int j = 1; j <= m; j ++) {
        cin >> a[i][j];
    }
}

问:输出第一行的所有数值

解:

第一行即第一个,这里 a[1] 是第一个数组,那么遍历输出第一个数组的所有元素即可。

for (int i = 1; i <= m; j ++) { 
     cout << a[1][i] << " ";
}

问:输出第 x 行的所有数值

解:

int x;
cin >> x;

for (int i = 1; i <= m; j ++) {
    cout << a[x][i] << " ";
}

与上一个问题无非就将 a[1] 一维数组替换为 a[x] 一维数组

问:输出第 1 列的所有数值

解:

第一列即每一个一维数组的第一个元素,即每一个一维数组 a[i] 的第一个元素 a[i][1]
for (int i = 1; i <= n; i ++) {
    cout << a[i][1] << ' ';
}

问:输出第 y 列的所有数值

解:

int y;
cin >> y;

for (int i = 1; i <= n; i ++) {
    cout << a[i][y] << " ";
}

问:输出 n*n 二维数组的左上角到右下角所有数值

解:

找出下标的规律,建议打草稿  (1,1) (2, 2) (3, 3) ... (n,n)

即 i == j 时即可

解法1:
for (int i = 1; i <= n; i ++) {
    cout << a[i][i] << " ";
}

解法2:
for (int i = 1; i <= n; i ++) {
    for (int j = 1; j <= n; j ++) {
         if (i == j) {
             cout << a[i][j] << ' ';
         }
    }
}


解法 1 只对该问写起来简单
解法 2 对所有下标有规律的问题,都适用。

思考:若要输出右上角到左下角的对角线数值呢?

思考:若中间位置的下标为 (i, j) , 那么四周其它的空白处的下标分别是什么呢?

image