【代码的暴力美学】-- C语言基础编程题_2


🔥个人主页: K 旺仔小馒头

🍉学习方向:C/C++方向学习者

📖个人专栏:《C语言》《数据结构与算法》《C++知识分享》《C语言实战编程》

⭐️人生格言:‌"何时葡萄先熟透,你要静候再静候"



前言:

本文围绕三个编程问题展开,涵盖等差数列求和、负整数统计与正整数均值计算,以及旋转数组最小值查找。结合数学公式与算法思维,解析如何把理论转化为高效代码,助力编程学习者提升实践能力。


一. 等差数列【难度:简单】

描述

对于首项为 2,公差为 3 的等差数列,求前 𝑛 项的和。

输入描述:

输入一个整数 𝑛(1≦𝑛≦10^3)。

输出描述:

输出一个整数,代表前 𝑛 项的和。

解析:

这道题了解了等差数列求和公式 Sn=n(a1+an)/2 就简单了,根据题目得知 a1=2,而等差数列第n项也有具体公式 an=a1+(n-1)d,而公差为3,这时候只需要套入公式计算即可。

cpp 复制代码
#include <stdio.h>

int main() {
    int n = 0;
    scanf("%d",&n);
    int a1 = 2;
    int sum = 0;
    sum = ((a1 + a1+3*(n-1))*n)/2;
    printf("%d",sum);

    return 0;
}

二. 记负均正【难度:简单】

描述

对于给定的 𝑛 个整数 𝑎1,𝑎2,⋯ ,𝑎𝑛,统计并计算:

∙  负整数的个数;

∙  正整数的平均值。

输入描述:

第一行输入一个整数 𝑛(1 ≦ 𝑛 ≦ 2×10^3) 代表整数的个数。

第二行输入 𝑛 个整数 𝑎1,𝑎2,...,𝑎𝑛(−10^3 ≦ 𝑎𝑖 ≦ 10^3) 代表输入的整数。

输出描述:

先输出一个整数,代表负整数的个数;随后在同一行输出一个实数,代表正整数的平均值。

由于实数的计算存在误差,当误差的量级不超过 10^−6时,您的答案都将被接受。具体来说,设您的答案为 𝑎 ,标准答案为 𝑏 ,当且仅当 ∣𝑎−𝑏∣ / max⁡(1,∣𝑏∣) ≦ 10^−6 时,您的答案将被接受。

解析:

  1. 输入处理:使用 scanf 读取整数个数 n ,然后循环读取 n 个整数。

  1. 统计与计算:遍历每个整数,统计负整数的个数 count1;对正整数,累加其和 sum 并统计正整数的个数 count2。

  1. 输出结果:计算正整数的平均值(若没有正整数则平均值为0),并按照要求输出负整数个数和保留六位小数的平均值。
cpp 复制代码
#include <stdio.h>

int main()
{
    int n = 0;
    scanf("%d",&n);//整数的个数
    
    int count1 = 0;//负整数的个数
    int count2 = 0;//正整数的个数
    double sum = 0;//正整数的总和
    int tmp = 0;//输入的整数

    for(int i = 0;i < n;i++)
    {
        scanf("%d",&tmp);

        if(tmp > 0)
        {
            sum += tmp;
            count2++;
        }
        else if(tmp < 0){
            count1++;
        }
    }
    double avg = count2 != 0 ? sum/count2 : 0.0;
    printf("%d %.6f",count1, avg);
    
    return 0;
}

三. 旋转数组的最小数字【难度:简单】

描述

有一个长度为 n 的非降序数组,比如1,2,3,4,5,将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了3,4,5,1,2,或者4,5,1,2,3这样的。请问,给定这样一个旋转数组,求数组中的最小值。

数据范围:1≤𝑛≤10000,数组中任意元素的值: 0≤𝑣𝑎𝑙≤10000

要求:空间复杂度:𝑂(1) ,时间复杂度:𝑂(𝑙𝑜𝑔𝑛)

解析:

  1. 暴力破解:遍历数组找出最小值即可

  2. 更优思想:采用二分查找

这个题主要分析三种旋转情况 1, 2, 3, 4, 5,使用中间值与右端进行比较。

a. 中间大于右边 3, 4, 5, 1, 2,这种情况下,最小数一定在右边;则left = mid + 1

b. 中间等于右边 1, 0, 1, 1, 1, 这个是0, 1, 1, 1, 1 旋转过来的,这时候需要缩小范围right--;注意不能是 left++,因为是非降序数组,所以要缩小右边范围,把较小值向右推,符合我们的判断规则。

c. 中间小于右边 5, 1, 2, 3, 4, 这种情况下,最小数字则在左半边;则right = mid

知识点:二分查找

取中间位置索引:

left + (right - left) / 2 和 (left + right) / 2 这两种写法,最终计算得到的"中间位置索引"是完全一致的,都是为了在二分查找中找到左右区间的中间点,从而缩小查找范围。

而 left + (right - left) / 2 之所以更"安全",核心就是避免了 left 和 right 直接相加时可能出现的整数溢出问题(比如当 left 和 right 本身很大,两者相加超过了整数类型的最大值时,用 (left + right) / 2 就会出错,而 left + (right - left) / 2 能规避这种情况)。

简单来说,二者"找中间点"的目标是一样的,只是 left + (right - left) / 2 在工程实践中更健壮~

注意:这个题目在牛客网里编译的话,你不用写main函数哈,别人会调用minNumberInRotateArray这个函数的(这个就相当于main函数);如果你再写一个main函数,就会报错(报错原因:有多个main函数)

牛客网里是这么给的代码,不需要再额外加main函数

cpp 复制代码
int minNumberInRotateArray(int* nums, int numsLen ) {
    // write code here //你只要在这里添加代码就好
}
cpp 复制代码
int minNumberInRotateArray(int* nums, int numsLen)
{
    int left = 0;
    int right = numsLen - 1;
    
    while (left < right) 
    {
        int mid = left + (right-left)/2;
        if(nums[mid] > nums[right])
        {
            left = mid + 1;
        }
        else if(nums[mid] < nums[right])
        {
            right = mid;
        }
        else 
        {
            right--;
        }
    }
    return nums[left];
}

结尾:

往期精选:

【代码的暴力美学】-- C语言基础编程题_1

结语:

文中三个编程问题的解法,体现了数学与算法在编程中的巧妙结合。从基础公式运用到复杂查找的优化,为编程学习者提供了将知识转化为高效代码的范例,期望能启发大家在编程之路上不断探索。

相关推荐
z落落9 小时前
C# 四种特殊类:抽象类、密封类、静态类、部分类
开发语言·c#
caimouse9 小时前
Reactos 第 4 章 对象管理 — 4.5 几个常用的内核函数
c语言·windows·架构
VidDown9 小时前
Webhook 调试器:让第三方回调“原形毕露”
java·开发语言·javascript·编辑器·postman
x1387028595710 小时前
c语言排雷游戏(基础版9*9)
c语言·算法·游戏
装不满的克莱因瓶10 小时前
基于 OpenResty 扩展开发实现动态服务注册与发现能力
java·开发语言·架构·openresty
caimouse10 小时前
Reactos 第 4 章 对象管理 — 4.3 句柄和句柄表(Handle & Handle Table)
c语言·windows·架构
weixin_5231853210 小时前
Java基础知识总结(四):引用数据类型与参数传递机制
java·开发语言·python
Nayxxu10 小时前
Claude API 生产稳定性设计:超时、降级、备用模型和告警怎么做
开发语言·php
王cb11 小时前
WinRT Server and Client c#
开发语言·c#
Selina K11 小时前
C中日历时间转换
c语言·开发语言