【无标题】数组知识点与习题2

数组

考点

  • 排序

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

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

  • 数组的基本操作

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

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

  • 二维数组 → 矩阵

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

用递归实现正序分离数的每一位


    //递归边界
    
    //n是个位数, 直接打印n
    // 46666
    // 4 6666
    // 6 666
    // 6 66
    // 6 6
    // 6
    //递归式子
#include <stdio.h>


#include <stdio.h>

void print(int n) // n为待分离的数
{
    if (n / 10 == 0)
    {
        printf("%d ", n);
    }
    else
    {
        print(n / 10);
        printf("%d ", n % 10);      
    }
}
int main()
{
    int n;
    scanf("%d", &n);
    
    print(n);
    return 0;
}

数组的插入

数组的随机访问O(1)

q[] 0 ~ 100

访问数组中的第三个数
q[2]

访问数组中的第100个数
q[99]

数组的插入O(n)

值 1 2 4 5 6
下标 0 1 2 3 4

插入3 → 把3后面的元素全都往后移一位

值 1 2 3 4 5 6
下标 0 1 2 3 4 5

数组的删除O(n)

值 1 2 4 5 6
下标 0 1 2 3 4

删除4 → 把4后面的元素全都往前移一位

值 1 2 5 6
下标 0 1 2 3

//方法一: 先把待插入的数放到数组里, 然后对新的数组排序
#include <stdio.h>

int q[200];
int main()
{
    int n, m;
    while(scanf("%d %d", &n, &m) != EOF)
    {
        if(n == 0 && m == 0) break;
        for (int i = 0; i < n; i++)
        {
            scanf("%d", &q[i]);
        }
        q[n] = m;
        //n + 1个元素, 下标0 ~ n
        //排序模板只需要把所有的n换成n + 1即可
        for(int i = 1; i <= n; i++)
        {
            for(int j = 0; j < n + 1 - i; j++)
            {
                if(q[j] < q[j + 1])
                {
                    int t = q[j];
                    q[j] = q[j + 1];
                    q[j + 1] = t;
                }
            }
        }
        for(int i = 0; i <= n; i++)
        {
            if(i)
            {
                printf(" %d", q[i]);
            }
            else printf("%d", q[i]);
        }

        printf("\n");
    }
    return 0;
}

//方法二、先找到插入的位置, 把后面的数整体后移一位, 插入元素
#include <stdio.h>

int q[200];
int main()
{
    int n, m;
    while (scanf("%d %d", &n, &m) != EOF)
    {
        if (n == 0 && m == 0)
            break;
        for (int i = 0; i < n; i++)
        {
            scanf("%d", &q[i]);
        }
        //普通查找 

        //找插入的位置pos
        int pos = n; //默认插入位置为n, 如果每一个数都比m大就插到q[n]
        for(int i = 0; i < n; i++) 
        {
            if(q[i] < m) //从前往后找第一个比它小的数 或者 从后往前找第一个比它大的数(pos以前的数要往前移动一位, 不好移)
            {
                pos = i;
                break;
            }
        }
        
        // 1 2 3 4 5
        // 1 x 2 3 4 5
        // 0 1 2 3 4 5
        //往后移位的时候, 从后往前移动, 并且把原来最后的一个数存一下

        int last = q[n - 1];
        for(int i = n - 1; i >= pos; i--)
        {
            q[i] = q[i - 1];
        }
        q[n] = last;
        
        //插入进去
        q[pos] = m;
        
        for(int i = 0; i <= n; i++)
        {
            if(i) printf(" %d", q[i]);
            else printf("%d", q[i]);
        }
        printf("\n");
    }

    return 0;
}

//思考: 如果把插入改成删除

删除第一个 <= m 的数

3 3
4 2 1
0 0

#include <stdio.h>

int q[200];
int main()
{
    int n, m;
    while (scanf("%d %d", &n, &m) != EOF)
    {
        if (n == 0 && m == 0)
            break;
        for (int i = 0; i < n; i++)
        {
            scanf("%d", &q[i]);
        }
        //找删除的数的位置 → 第一个 <= m 的数
        int pos = n;
        for(int i = 0; i < n; i++)
        {
            if(q[i] <= m)
            {
                pos = i;
                break;
            }
        }
        if(pos == n)
        {
            printf("没有<=m的数\n");
            continue;
        }

        for(int i = pos; i <= n - 1; i++) //pos的位置被代替了, 因此不需要有额外的删除操作
        {
            q[i] = q[i + 1];
        }
        // 1 2 3 4  5  
        // 1 2 4 5 0/5
        for (int i = 0; i < n - 1; i++)
        {
            if (i)
                printf(" %d", q[i]);
            else
                printf("%d", q[i]);
        }
        printf("\n");
    }

    return 0;
}

数组移位

//往后移

往后移动m次等价于往后移动m % n次

往后移动 → 从后往前写for
从第一个数到第n - 1个数都往后移动1位, 再把第一个数替换为原来的最后一个数

1 2 3 4 5
5 1 2 3 4 m = 1
4 5 1 2 3 m = 2
3 4 5 1 2 m = 3
2 3 4 5 1 m = 4
1 2 3 4 5 m = 5

5 1 2 3 4 m = 6
4 5 1 2 3 m = 7
3 4 5 1 2 m = 8
2 3 4 5 1 m = 9
1 2 3 4 5 m = 10

#include <stdio.h>

int q[150];
int main()
{
    int n;
    scanf("%d", &n);
    for(int i = 0; i < n; i++) scanf("%d", &q[i]);
    int m;
    scanf("%d", &m); //移动m次

    //步骤: 记录一下最后一个数t, 从第一个数到第n-1个数往后移动1位, 第一个数替换为t

    while(m--)
    {
        int t = q[n - 1];
        for(int i = n - 1; i >= 1; i--) //往后移动, 从后往前写, 注意结束是到1
        {
            q[i] = q[i - 1];
        }
        q[0] = t;
    } 
    for(int i = 0; i < n; i++)
    {
        if(i) printf(" %d", q[i]);
        else printf("%d", q[i]);
    }
    return 0;
}


//往后移动m次等价于往前移动n - m次

后n次一个循环

只需要移动(100 % n)次 → m = m % n;

往后移动m次相当于往前移动 n - m % n 次


往后移动m次相当于往前移动 n - m % n 次

//往前移

往前移, 从前往后写for
1 2 3 4 5
2 3 4 5 1 m = 1
3 4 5 1 2 m = 2
4 5 1 2 3 m = 3
5 1 2 3 4 m = 4
1 2 3 4 5 m = 5

7-18 sdut-C语言实验-矩阵输出(数组移位)

#include <stdio.h>

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

    // 步骤: 记录一下最后一个数t, 从第一个数到第n-1个数往后移动1位, 第一个数替换为t
    while (m--)
    {
        for (int i = 0; i < n; i++)
        {
            if (i)
                printf(" %d", q[i]);
            else
                printf("%d", q[i]);
        }
        printf("\n");
        int t = q[n - 1];
        for (int i = n - 1; i >= 1; i--) // 往后移动, 从后往前写, 注意结束是到1
        {
            q[i] = q[i - 1];
        }
        q[0] = t;
    }

    return 0;
}
日期处理
//判断闰年
int is_leap(int n)
{
    //xx00  xxxx
    if(n % 400 == 0 || (n % 100 != 0) && n % 4 == 0) return 1;
    else return 0;
}

//存某月的天数
int month[2][13] = {{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};

d = month[is_leap(y)][m];//y年m月对应的天数

7-6 sdut- C语言实验-数日子
#include <stdio.h>
int is_leap(int n)
{
    // xx00  xxxx
    if (n % 400 == 0 || (n % 100 != 0) && n % 4 == 0)
        return 1;
    else
        return 0;
}

int month[2][13] = {{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};

int main()
{
    int y, m, d;
    int n;
    scanf("%d", &n);
    while(n--)
    {
        int sum = 0;
        scanf("%d %d %d", &y, &m, &d);
        for(int i = 1; i < m; i++) //m月之前已经过完了, 直接把对应月份的所有天数加起来
        {
            sum += month[is_leap(y)][i];
        }
        sum += d; //当前的m月已经过了d天
        printf("%d\n", sum);
    }


    return 0;
}
###二维数组矩阵转置小引
```int q[5][10];

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

1111111111
1111111111
1111111111
1111111111
1111111111

(m * n) * (s * t)

n = s
m * t

1234    
2314

1324
1234
1423
2143

2*4  4*4  2*4


xxxx
xxxx


123   
321  
213   
 
313
122
231


231
122
313

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值