【代码的暴力美学】-- 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

结语:

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

相关推荐
豐儀麟阁贵12 分钟前
4.4数组的基本操作
java·开发语言·数据结构·算法
Moniane13 分钟前
XMW技术:颠覆未来的创新引擎
开发语言
组合缺一17 分钟前
全球首个支持 IETF JSONPath (RFC 9535) 标准的 Java 框架,Snack4-Jsonpath v4.0.0 发布
java·开发语言·json·jsonpath
无限进步_22 分钟前
【C语言】在矩阵中高效查找数字的算法解析
c语言·开发语言·数据结构·c++·其他·算法·矩阵
jghhh0127 分钟前
超声波数值模拟与声场传播的MATLAB实现
开发语言·matlab
pcm12356734 分钟前
内置线程池的核心参数分析配置
java·开发语言
Yupureki42 分钟前
从零开始的C++学习生活 11:二叉搜索树全面解析
c语言·数据结构·c++·学习·visual studio
草莓工作室44 分钟前
数据结构2:线性表1-线性表类型及其特点
c语言·数据结构
啊森要自信1 小时前
【MySQL 数据库】MySQL用户管理
android·c语言·开发语言·数据库·mysql
代码不停1 小时前
JavaEE初级 多线程案例(单例模式、阻塞队列、线程池、定时器)
java·开发语言·单例模式·java-ee