二维数组正式讲+田忌赛马

考点

  • 排序

    • 冒泡排序 O(n^2)
    • 选择排序 O(n^2)
    • (插入排序)
  • 分离每一位

    • 正序
      • 字符串
      • 栈(递归)
    • 逆序
  • 哈希(hash) → 用值直接作为下标

  • 数组的基本操作

    • 插入和删除
    • 逆序(移位)
  • 日期处理问题

  • 7 - 19田忌赛马 (双指针)

  • 二维数组 → 矩阵

    • 矩阵转置
    • 判断对称矩阵
    • 矩阵运算
    • 矩阵移位
  • 杨辉三角

二维数组

二维数组 → 很多一维数组

int q[n][m];

n个大小为m的一维数组组成的s

123
456
789

for(int i = 0; i < n; i++) //行  
{
  for(int j = 0; j < m; j++) //列
  {
    scanf("%d", &q[i][j]);
    printf("%d", q[i][j]);
  }
}

矩阵的加法

  • 条件: 两个矩阵的行和列相同
a * b
m * n

6 5 1
2 1 4

7 8 9
6 1 3

13 13 10
8  2  7

a = m, b = n

int p[150][150];
int q[150][150];
int ans[150][150];

for(int i = 0; i < a; i++)
{
    for(int j = 0; j < b; j++)
    {
        scanf("%d", &p[i][j]);
    }
}

for(int i = 0; i < m; i++)
{
    for(int j = 0; j < n; j++)
    {
        scanf("%d", &q[i][j]);
    }
}

for(int i = 0; i < n; i ++)
{
    for(int j = 0; j < m; j++)
    {
        ans[i][j] = p[i][j] + q[i][j];
    }
}
for(int i = 0; i < n; i ++)
{
    for(int j = 0; j < m; j++)
    {
        printf("%d ", ans[i][j]);
    }
}


矩阵的乘法

  • 要求第一个矩阵的列 = 第二个矩阵的行, 最终答案为第一个矩阵的行 * 第二个矩阵的列
    a * b

m * n
b = m

第一个矩阵的列 = 第二个矩阵的行

结果为a * n的矩阵


3 * 2   2 * 3

1 2     1 2 3
1 3     3 4 5
1 4

第一个矩阵的行 *  第二个矩阵的列

```cpp
int p[150][150];
int q[150][150];
for(int i = 0; i < a; i++) //a * b
{
    for(int j = 0; j < n; j++) // m * n
    {
        //计算ans[i][j]
        for(int k = 0; k < b; k++)  // k < m也可以
        {
            ans[i][j] += p[i][k] * q[k][j];
        }
        
    }
}

for(int i = 0; i < a; i++)
{
    for(int j = 0; j < n; j++)
    {
        printf("%d ", ans[i][j]);
    }
    printf("\n");
}

//计算结果矩阵的第(i, j)个元素的时候, 需要用第一个矩阵的第i行的所有元素分别与第二个矩阵的第j列的所有元素分别相乘再相加

x1 = 1 * 1 + 2 * 3
x2 = 1 * 2 + 2 * 4
x3 = 1 * 3 + 2 * 5
x4 = 1 * 1 + 3 * 3
x5 = 1 * 2 + 3 * 4
x6 = 1 * 3 + 3 * 5
x7 = 1 * 1 + 4 * 3
x8 = 1 * 2 + 4 * 4
x9 = 1 * 3 + 4 * 5

x1 x2 x3
x4 x5 x6
x7 x8 x9

#include <stdio.h>

int p[150][150];
int q[150][150];
int ans[150][150];
int main()
{
    int a, b, m, n;
    scanf("%d %d %d %d", &a, &b, &m, &n);


    for(int i = 0; i < a; i++)
    {
        for(int j = 0; j < b; j++)
        {
            scanf("%d", &p[i][j]);
        }
    }
    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++)
        {
            scanf("%d", &q[i][j]);
        }
    }

    for(int i = 0; i < a; i++) //a * b
    {
        for(int j = 0; j < n; j++) // m * n
        {
            //计算ans[i][j]
            for(int k = 0; k < b; k++)  // k < m也可以
            {
                ans[i][j]  += p[i][k] * q[k][j];
            }
            // printf("%d ", ans[i][j]);
        }
        printf("\n");
    }

    for(int i = 0; i < a; i++)
    {
        for(int j = 0; j < n; j++)
        {
            printf("%d ", ans[i][j]);
        }
        printf("\n");
    }
    return 0;
}

求对角线元素之和


m * m

int a[150][150];
int sum = 0;
for(int i = 0; i < m; i++)
{
    sum += a[i][i];
}

7-2 求矩阵各行元素之和

for(int i = 0; i < n; i++)
{
    int sum = 0;
    for(int j = 0; j < m; j++)  
    {
        sum += q[i][j];  
    }
    printf("%d\n", sum);
}

对称矩阵

  • 对称矩阵 → 关于主对角线对称, 必须行和列相同
    a[i][j] 是否== a[j][i]

#include <stdio.h>

int q[50][50];
int main()
{
    int n;
    while(scanf("%d", &n) != EOF)
    {
        if(n == 0) break;

        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < n; j++)
            {
                scanf("%d", &q[i][j]);
            }
        }

        int f = 1;//用来标记是否是对称矩阵
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < n; j++)
            {
                if(q[i][j] != q[j][i])
                {
                    f = 0;
                    break;  
                }
            }
            if(f == 0) break;
        }
        if(f == 0)
            printf("No.\n");
        else
            printf("Yes.\n");
    }
    return 0;
}

杨辉三角

  1
1   1

1 2 1
1 3 3 1
1 4 6 4 1

1
1 1
1 2 1
1 3 3 1
1 4 6 4 1

0 0 0 0 0 0 0
0 1 0 0 0 0 0
0 1 1 0 0 0 0
0 1 2 1 0 0 0
0 1 3 3 1 0 0
0 1 4 6 4 1 0

#include <stdio.h>

int q[50][50];


int main()
{
    int n;
    while(scanf("%d", &n) != EOF)
    {
        if(n == 0) break;

        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= i; j++)
            {
                if(j == 1 || j == i)
                {
                    q[i][j] = 1;
                }
                else q[i][j] = q[i - 1][j] + q[i - 1][j - 1];
            }
        }

        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= i; j++)
            {
                if (j == 1)
                    printf("%d", q[i][j]);
                else
                    printf(" %d", q[i][j]);
            }
            printf("\n");
        }
        printf("\n");

    }

    return 0;
}

7-5 sdut-C语言实验- 鞍点计算

#include <stdio.h>

int q[20][20];
int main()
{
    int m, n;

    scanf("%d %d", &m, &n);

    for(int i = 0; i < m; i++)
    {
        for(int j = 0; j < n; j++)
        {
            scanf("%d", &q[i][j]);
        }
    }

    
    int f = 1; 
    for(int i = 0; i < m; i++)
    {
        for(int j = 0; j < n; j++)
        {
            
            //拿到(i, j)点,i和j就固定了, 
            //假设当前(i, j)为鞍点, 更新ans_x, ans_y, ans, f

            f = 1;
            int ans_x = i, ans_y = j;
            int ans = q[i][j];

            //是否在该行上最大 (行i固定, 遍历列)
            for(int k = 0; k < n; k++)
            {
                if(q[i][k] > q[i][j]) 
                {
                    f = 0;
                    break;
                }
            }
            // 是否在该列最小 (列j固定, 遍历列)
            for(int k = 0; k < m; k++)
            {
                if(q[k][j] < q[i][j])
                {
                    f = 0;
                    break;
                }
            }
            if(f == 1)
            {
                printf("Array[%d][%d]=%d\n", ans_x, ans_y, ans);
                return 0;
            }
        }
    }
    if(f == 0) //如果n * m个点都比较完了而且都不是鞍点, 说明没有鞍点
        printf("None\n");
    return 0;
}

矩阵移位

矩阵旋转

矩阵转置

q[i][j] = q[j][i]

定义一个新的数组ans, ans[j][i] = q[i][j]

#include <stdio.h>

int q[150][150];
int ans[150][150];

int main()
{
    int n;
    scanf("%d", &n);
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            scanf("%d", &q[i][j]);
            ans[j][i] = q[i][j];
        }
    }

    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            if(j == 0) printf("%d", ans[i][j]);
            else printf(" %d", ans[i][j]);
        }
        printf("\n");
    }
    return 0;
}

m = m % n
假设下标为i, 移动m次后成为了新的第一个数
最后一个数下标为n - 1
i ~ n - 1 一共有n - 1 - i + 1 = n - i个数, i到n-1需要移动 n - i - 1次

最后一个元素(下标n - 1) → 第一个元素还需要在移动一次

n - i - 1 + 1次 = m

→ i = n - m(必须保证这个i是正的)

[n - m, n - 1]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值