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

结语:

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

相关推荐
MediaTea2 小时前
Python 编辑器:Visual Studio Code
开发语言·ide·vscode·python·编辑器
懒羊羊不懒@2 小时前
C语言指针进阶(进阶)
java·开发语言·面试
前路不黑暗@3 小时前
Java:代码块
java·开发语言·经验分享·笔记·python·学习·学习方法
Pocker_Spades_A3 小时前
C++程序设计上机作业(1)
开发语言·c++
乱飞的秋天3 小时前
C++中的特殊成员函数
开发语言·c++
小严家3 小时前
Flutter完整开发指南 | Flutter&Dart – The Complete Guide
开发语言·flutter
宇宙的尽头是PYTHON3 小时前
用生活中的实例解释java的类class和方法public static void main
java·开发语言·生活
道传科技上位机4 小时前
C# 循环和条件用法大全(while dowhile for foreach if Switch try)全站最全
开发语言·c#
寻星探路4 小时前
Java EE初阶启程记04---线程的状态
java·开发语言·jvm·java-ee