牛客网刷题(2)

文章目录

  • 一、学习刷题网站
  • 二、刷题
    • <1>有序序列插入一个数
    • <2>有序序列判断
      • 暴力判断法
      • 标志位法
    • <3>序列中删除指定数字
      • 普通删除(移动法)
      • 进阶删除(跳过法)
    • <4>序列中整数去重
      • 普通去重(移动法)
      • 进阶去重(标志位法)
    • <5>有序序列合并
      • 暴力排序输出
      • 平行对比法
    • <6>筛选法求素数
    • <7>X形图案

一、学习刷题网站

在这里插入图片描述

点击下面链接即可进行刷题学习
开始刷题

二、刷题

<1>有序序列插入一个数

牛客网刷题(2)_第1张图片
要插入数字k有三种情况:
1️⃣k在数组中
2️⃣k在数组最右边
3️⃣k在数组最左边
对第1️⃣种情况我们可以采取数组从最后一个元素开始右移的方法,每次判断k是否大于指定数,当大于时就插入。
第2️⃣种情况可以包含在第一种情况(k大于最后一个元素,直接插入)。
第3️⃣种情况就是当第一个元素被移到第二个位置时,直接就把k放在第一个元素的位置就行了。
代码如下:

int main()
{
    int n = 0;
    scanf("%d", &n);
    int arr[51] = {0};
    int i = 0;
    for(i = 0; i < n; i++)
    {
        scanf("%d", &arr[i]);
    }
    
    int k = 0;
    scanf("%d", &k);
    //数组后移途中插入k
    for(i = n; i > 0; i--)
    {
        if(arr[i - 1] > k)
        {
            arr[i] = arr[i - 1];
        }
        else
        {
            arr[i] = k;
            break;
        }
    }
    //当k小于所有数字时
    if(i == 0)
    {
        arr[0] = k;
    }
    
    for(i = 0; i < n + 1; i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

<2>有序序列判断

牛客网刷题(2)_第2张图片

暴力判断法

直接用最后一个元素减第一个元素,有三种情况:
1️⃣大于0,遍历数组,俩俩比较,都<,则sorted,否则unsorted。
2️⃣小于0,遍历数组,俩俩比较,都>,则sorted,否则unsorted。
3️⃣等于0,遍历数组,俩俩比较,都=,则sorted,否则unsorted。
代码如下:

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

    int tmp = arr[n - 1] - arr[0];
    int jud = 0;
    if (0 == tmp)
    {
        for (i = 0; i < n - 1; i++)
        {
            if (arr[i] != arr[i + 1])
            {
                jud = -1;
                break;
            }
        }
    }
    else if (tmp > 0)
    {
        for (i = 0; i < n - 1; i++)
        {
            if (arr[i] > arr[i + 1])
            {
                jud = -1;
                break;
            }
        }
    }
    else
        for (i = 0; i < n - 1; i++)
        {
            if (arr[i] < arr[i + 1])
            {
                jud = -1;
                break;
            }
        }
    if (jud == 0)
    {
        printf("sorted\n");
    }
    else
    {
        printf("unsorted\n");
    }
    return 0;
}

标志位法

创造两个标志位flag1和flag2, flag1表示升序, flag2表示降序, 最后
flag1 + flag2 == 1, 则有序。
代码如下:

int main()
{
    int n = 0;
    scanf("%d", &n);
    int arr[50] = {0};
    int i = 0;
    for(i = 0; i < n; i++)
    {
        scanf("%d", &arr[i]);
    }
    //升序标志
    int flag1 = 0;
    //降序标志
    int flag2 = 0;
    for(i = 0; i < n - 1; i++)
    {
        if(arr[i] < arr[i + 1])
        {
            flag1 = 1;
        }
        else
        {
            flag2 = 1;
        }
    }
    
    if(flag1 + flag2 == 1)
    {
        printf("sorted\n");
    }
    else
    {
        printf("unsorted\n");
    }
    return 0;
}

<3>序列中删除指定数字

牛客网刷题(2)_第3张图片

普通删除(移动法)

遍历数组,找到要删除数字del对应的位置,把后边的元素都往前移。这里要注意每次移动完后数组长度都要减1,找到的元素的下标也要减1(如果俩个要删除的数字挨在一起,就会跳过第二个)

代码如下:

int main()
{
    int n = 0;
    scanf("%d", &n);
    int arr[50] = {0};
    int i = 0;
    for(i = 0; i < n; i++)
    {
        scanf("%d", &arr[i]);
    }
    
    int del = 0;
    scanf("%d", &del);
    for(i = 0; i < n; i++)
    {
        //找到指定元素
        if(arr[i] == del)
        {
            int j = 0;
            for(j = i; j < n - 1; j++)
            {
                arr[j] = arr[j + 1];
            }
            n--;
            i--;
        }
    }
    for(i = 0; i < n; i++)
    {
    printf("%d ", arr[i]);
    }
    return 0;
}

进阶删除(跳过法)

用图来表示:
牛客网刷题(2)_第4张图片
如果i指向的不是要删除的就arr[ j ] = arr[ i ], i , j都后移
如图:
牛客网刷题(2)_第5张图片
当i指向的是要删除的元素时,j 不动, i 跳到不是要删除的元素的位置
如图
牛客网刷题(2)_第6张图片
此时得注意元素个数变成了 j 。

代码如下:(上部分都一样的,不浪费篇幅)

    int j = 0;
    for(i = 0; i < n; i++)
    {
        if(arr[i] != del)
        {
        arr[j++] = arr[i];
        }
    }
    //此时元素个数为 j 个
    for(i = 0; i < j; i++)
    {
    printf("%d ", arr[i]);
    }

<4>序列中整数去重

牛客网刷题(2)_第7张图片

普通去重(移动法)

思路:
1️⃣去重第一个元素:从第二个元素开始遍历数组,找到相同的元素,向左移动数组,没有则不移。
2️⃣去重第二个元素:从第三个元素开始遍历数组,找到相同的元素,向左移动数组,没有则不移。
…………
代码如下:

int main()
{
    int n = 0;
    scanf("%d", &n);
    int i = 0;
    int arr[1000];
    for(i = 0; i < n; i++)
    {
        scanf("%d", &arr[i]);
    }
    
    int j = 0;
    for(i = 0; i < n; i++)
    {
        for(j = i + 1; j < n; j++)
        {
            if(arr[j] == arr[i])
            {
                //移动
                int k = 0;
                for(k = j; k < n - 1; k++)
                {
                    arr[k] = arr[k + 1];
                }
                n--;
                j--;
            }
        }
    }
    for(i = 0; i < n; i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

进阶去重(标志位法)

思路:不用移动数组,类似上题的跳过法,跟已经输出的元素比较,发现有相同的元素直接跳过不输出就行了。
代码如下:

for(i = 0; i < n; i++)
    {
        int flag = 1;
        int j = 0;
        //输出前和前面的元素比较
        for(j = 0; j < i; j++)
        {
            if(arr[i] == arr[j])
            {
                flag = 0;
            }
        }
        if(flag)
        {
            printf("%d ", arr[i]);
        }
    }

只要发现有和前面相同的,flag就会改为0,条件为假就不会输出。


<5>有序序列合并

牛客网刷题(2)_第8张图片

暴力排序输出

这道题是让我们把俩个数组一起排好序输出,我们可以直接把他们放在一个数组里直接简单粗暴排序并输出。
代码如下:

int cmp_int(const void* e1, const void* e2)
{
    return *(int*)e1 - *(int*)e2;
}

int main()
{
    int n = 0;
    int m = 0;
    scanf("%d %d", &n, &m);
    int i = 0;
    int arr[2000] = {0};
    for (i = 0; i < n; i++)
    {
        scanf("%d", &arr[i]);
    }
    
    for (i = n; i < m + n; i++)
    {
        scanf("%d", &arr[i]);
    }
    qsort(arr, m + n, 4, cmp_int);
        
        for (i = 0; i < m + n; i++)
        {
            printf("%d ", arr[i]);
        }
    return 0;
}

这里用到库函数qsort函数,不明白的同学请看我的另一篇博客中的争夺前五名的题目

平行对比法

俩个数组从头开始比较,每次都输出较小的,输出完后往后移动一位。直到一个数组输出完后,直接按顺序输出另一个数组的剩余所有数。
如图:
牛客网刷题(2)_第9张图片
代码如下:

int main()
{
    int n = 0;
    int m = 0;
    scanf("%d %d", &n, &m);
    int arr1[1000] = {0};
    int arr2[1000] = {0};
    int i = 0;
    for(i = 0; i < n; i++)
    {
        scanf("%d", &arr1[i]);
    }
    for(i = 0; i < m; i++)
    {
        scanf("%d", &arr2[i]);
    }
    //俩"箭头"
    i = 0;
    int j = 0;
    while(i < n && j < m)
    {
        if(arr1[i] < arr2[j])
        {
            printf("%d ", arr1[i]);
            i++;
        }
        else
        {
            printf("%d ", arr2[j]);
            j++;
        }
    }
    //输出剩余元素
    if(i < n)
    {
        for(; i < n; i++)
        {
            printf("%d ", arr1[i]);
        }
    }
    else
    {
        for (; j < m; j++)
        {
            printf("%d ", arr2[j]);
        }
    }
    return 0;
}

<6>筛选法求素数

牛客网刷题(2)_第10张图片
要注意的问题:
要把2 ~ n的数字放到数组里,数组的大小要 [ n + 1 ] (n个元素)。


代码如下:

int main()
{
    int n = 0;
    while(~scanf("%d", &n))
    {
        //n 个元素要n + 1 的数组
        int arr[n + 1];
        int i = 0;
        //初始化
        for(i = 0; i <= n; i++)
        {
            arr[i] = i;
        }
        //从2开始
        for(i = 2; i <= n; i++)
        {
            int j = 0;
            for(j = i + 1; j <= n; j++)
            {
                if(arr[j] % i == 0)
                {
                    arr[j] = 0;
                }
            }
        }
        
        int count = 0;    
        for(i = 2; i <= n; i++)
        {
            if(arr[i])
            {
                printf("%d ", arr[i]);
            }
            else
            {
                count++;
            }
        }
        printf("\n%d\n", count);
    }
    
    return 0;
}

<7>X形图案

牛客网刷题(2)_第11张图片
首先找到规律:
\ :右斜线横行和纵列数相等
/ :左斜线横行和纵列数相加值一样
要注意的:
不要忘了其他地方打印空格。


代码如下:

int main()
{
    int n = 0;
    while(~scanf("%d", &n))
    {
        int i = 0;
        int j = 0;
        for(i = 0; i < n; i++)
        {
            for(j = 0; j < n; j++)
            {
                if(i == j || i + j == n - 1)
                {
                    printf("*");
                }
                else
                {
                    printf(" ");
                }
            }
            printf("\n");
        }
            
    }
    return 0;
}

点击链接[一起刷题吧]

你可能感兴趣的:(百炼成钢,c语言,算法)