力推C语言必会题目终章(完结篇)

这篇具有很好参考价值的文章主要介绍了力推C语言必会题目终章(完结篇)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

力推C语言必会题目终章(完结篇),c语言,开发语言

W...Y的主页 😊

代码仓库分享 💕

今天是分享C语言必会题目最终章,全部都是硬货,大家都坐好准备开始喽!!!

编写一个函数,计算字符串中含有的不同字符的个数。字符在 ASCII 码范围内( 0~127 ,包括 0 和 127 ),换行 表示结束符,不算在字符里。不在范围内的不作统计。多个相同的字符只计算一次

例如,对于字符串 abaca 而言,有 a、b、c 三种不同的字符,因此输出 3 。

数据范围: 0 <= n <= 500

输入描述:输入一行没有空格的字符串。

输出描述:输出 输入字符串 中范围在(0~127,包括0和127)字符的种数。

OJ链接【牛客网题号: HJ10 字符个数统计】

示例: 输入:abc 输入:aaa

            输出:3 输出:1


这道题非常简单,ASCII码的范围为127,我们只需要创建一个char类型的数组进行全部初始化为0,然后将字符作为数组下标在数组中进行标记,若数组中没有标记过表示第一次出现,进行计数,否则表示重复字符。

示例:查表法, "aaa" ,首先把a字符( ascii 值为 97 )作为下标,将标记数组的第 97 位置 1 ,下次如果还有 a 字符出 现,到下标 'a' 或者 97 的位置一看是1就表示a已经统计过了,使用if进行判断即可成功。

下面为代码实现:

#include <stdio.h>

int main() {
    char tmp[501] = {0};
    while(scanf("%s", tmp) != EOF)
    {
        char mark[128] = {0};
        int count = 0;
        char *ptr = tmp;
        while(*ptr)
        {
            if(mark[*ptr] != 1)
            {
                count++;
            }
            mark[*ptr] = 1;
            ptr++;
        }
        printf("%d\n", count);
    }
    return 0;
}

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。

OJ链接【 leetcode 题号:169. 多数元素】 

示例 1:

输入:nums = [3,2,3]
输出:3

示例 2:

输入:nums = [2,2,1,1,1,2,2]
输出:2
提示:

n == nums.length 

1 <= n <= 5 * 104

进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。


解法一:

首先我们得清楚这个数组中一定会有一个元素出现次数大于等于n/2,所以当我们排序后再取中间的元素返回一定是多数元素。(只需要极少量的代码即可完成)

时间复杂度O(nlogn),空间复杂度O(1)。

#include <stdio.h>
#include<string.h>
#include<stdlib.h>

int compar(const void* p1, const void* p2)
{
	return *(int*)p1 - *(int*)p2;
}


int majorityElement(int* nums, int numsSize){
    qsort(nums, numsSize,sizeof(int), compar);
    
    return nums[numsSize / 2];
}

进阶解法二:

一个数组中有一个数字出现次数大于 n/2 ,从第 0 个字符开始,假设它就是最多的那个数字,遇到相同的数字则 计数 +1 , 遇到不同的则计数 -1 ,其实就是互相消耗,等到计数为 0 的时候,表示本次互拼完毕,从下一个字符重 新开始互拼,但是归根结底出现次数大于 n/2 的这个数字数量更多,因此也是最后保留的字符。

示例: "23335" 首先从字符 2 开始计数 1 ,遇到 3 ,不同则 -1 ,互拼消耗 重新从剩下的 "335" 开始的过程,这时 候保存的字符为 3 ,遇到 3 则计数 +1 , 遇到5则计数 -1 ,在计数不为 0 时,走到末尾保存的字符就是个数超过 n/2 的字符。

这种方法不容易被想到,但是优化了时间复杂度。

int majorityElement(int* nums, int numsSize){
    int count = 1;
    int tmp = nums[0];
    for(int i = 1; i < numsSize; i++)
    {
            if(tmp == nums[i])
            {
                count++;
            }
            else
            {
                count--;
            }
            if(count == 0)
            {
                tmp = nums[i+1];
            }
    }
    return tmp;
}

 写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。

数据范围:两个数都满足 0≤n≤1000

OJ链接【牛客网题号: JZ65 不用加减乘除做加法】     

进阶:空间复杂度 O(1),时间复杂度O(1)   

示例: 输入:1,2 返回值:3


十进制相加思想: 15+07 , 先计算不考虑进位的相加结果 12 (因为 5+7 的不考虑进位的结果是 2 ,遇 10 进位 嘛),然后计算进位 5+7 进位是 10 ,则 10 与 12 再次相加,得到 22 ,进位为 0 ,则计算到此结束。

这里使用二进制求和完成,思想类似,但是二进制计算相加和进位不需要使用 + 符号

二进制相加思想:与十进制相同,先计算不考虑进位的相加结果( 0+0 得 0 , 1+1 进位得 0 , 1+0 得 1 ),使用 异或可以取得; 然后计算相加的进位结果(同 1 的位置左移一位即可),使用相与后左移取得。

示例:

5   0101 + 7   0111 不考虑进位的相加结果 0101^0111 -> 0010 相加的进位 0101&0111 -> 0101 因为进位左移得到 1010

1010 + 0010 不考虑进位的相加结果 1010 ^ 0010 -> 1000 相加的进位 1010 & 0010 -> 0010 因为进位左移得到 0100

1000 + 0100 不考虑进位的相加结果 1000 ^ 0100 -> 1100 相加的进位 1000 & 0100 -> 0000 进位为0结束运算。

int Add(int num1, int num2 ) {
   int sum = 0;
   while(num2 != 0)//进位不为0则持续与相加结果进行相加
   {
    sum = num1 ^ num2;//进位不为0则持续与相加结果进行相加
    num2 = (num1 & num2) << 1;//同1的位相加则会进位
    num1 = sum;
   }

   return num1;
}

 1、给定一个二进制数组, 计算其中最大连续 1 的个数。

OJ链接【 leetcode 题号:485. 最大连续 1 的个数】

示例: 输入:[1,1,0,1,1,1] 输出:3

解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3.


这道题思路比较简单,统计连续1的个数,遇到0时表示连续中断,判断如果当前的统计数大于之前最大的则替换, 然后继续下一个位置开始的统计即可。

int findMaxConsecutiveOnes(int* nums, int numsSize){
    int max = 0;
    int count = 0;
    for(int i = 0; i < numsSize; i++)
    {
        if(nums[i] == 1)
        {
            count++;
            if(max < count)
            {
                max = count;
            }
        }
        else
        {
            count = 0;
        }
    }
    return max;
}

求输出n以内(含n)完全数的个数。完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数。 它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身。

例如:28,它有约数1、2、4、7、14、28,除去它本身28外,其余5个数相加,1+2+4+7+14=28。

注意:本题输入含有多组样例。

输入描述:输入一个数字n 输出描述:输出不超过n的完全数的个数

OJ链接【牛客网题号: HJ56 完全数计算】

示例: 输入:1000 7 100 输出:3 1 2


这道题的关键在于完全数的判断:完全数指的是一个数字的所有约数的和和自身相等。我们只需要从 1 开始将这个 数的约数相加求和即可。

约数就是能够被数字整除,而这里简化的一个思路是数字能够被整除,则除数和结果就都是约数,这种思路下,只 需要从1计算到平方根即可

比如:数字 8 , 能够整除 2 ,结果是 4 ,则除数 2 和结果 4 都是约数,而这两个只需要一次计算判断即可。

需要注意的是 4,9,25... 这种,除数和结果相同的情况,则除数或者结果只相加一次就够了。

#include <stdio.h>
#include<math.h>
int is_perfect_num(int num)
{
int sum = 1;
for (int i = 2; i <= sqrt(num); i++) {
if (num % i == 0) {//判断是否能够整除i,能整除则i和结果都是约数
sum += i; //与除数相加
if (i != sqrt(num))//防止除数和结果相同的情况下重复相加
sum += num / i; //与相除结果相加
}
}
if (sum == num) return 1;
return 0;
}
int main()
{
int n;
while(~scanf("%d", &n)){
int count = 0;
for(int i = 2; i <= n; i++) {//对n以内的数字都进行判断是否是完全数,注意1不参与判断
if (is_perfect_num(i)) count++;
}
printf("%d\n", count);
}
return 0;
}

数列的定义如下:数列的第一项为n,以后各项为前一项的平方根,求数列的前m项的和。 输入描述: 输入数据有多组,每组占一行,由两个整数 n(n<10000) 和 m(m<1000) 组成,n和m的含义如前所述。

输出描述: 对于每组输入数据,输出该数列的和,每个测试实例占一行,要求精度保留2位小数。

OJ链接【牛客网题号: ZJ16 数列的和】 

输入:

81 4
2 2

输出:

94.73
3.41

求取一个数字的平方根可以使用数学库中的 double sqrt(double num) 函数完成,接下来只需要从数字自身开始进行 求和并在求和后将 n 自身计算成为自身的平方根即可。

#include <stdio.h>
#include<math.h>
int main() {
    double m, n;
    while(scanf("%lf %lf", &n, &m) != EOF)
    {
        double sum = 0;
        while(m-- > 0)
        {
            sum +=n;
            n = sqrt(n);
        }
        printf("%.2lf\n",sum);
    }
    return 0;
}

现在有一个长度为 n 的正整数序列,其中只有一种数值出现了奇数次,其他数值均出现偶数次,请你找出那个 出现奇数次的数值。

输入描述:第一行:一个整数n,表示序列的长度。第二行:n个正整数ai,两个数中间以空格隔开。

输出描述:一个数,即在序列中唯一出现奇数次的数值。

OJ链接【牛客网题号: KS33 寻找奇数】

示例: 输入:5 2 1 2 3 1 输出:3


异或:二进制比特位相同则0, 不同则1.

异或法:两个相同的数字异或得到的是0, 基于这个思路,这道题对数组中的所有数据进行逐一异或就可以解决得到奇数次 的数字,因为偶数次的数字都被异或成为0了,最后单独保留了奇数次的数字。

#include <stdio.h>

int main() {
    int n;
    while(~scanf("%d", &n))
    {
        int num = 0, tmp = 0;
        //对每个数字进行异或,出现偶数次的就会异或为0了,而奇数次刚好剩下的就是对应数字
        for (int i = 0; i < n; i++)
         {
            scanf("%d", &tmp);
            num ^= tmp;
        }
        printf("%d\n", num);
    }
    return 0;
}

给定一个长度为n的数组 nums ,请你找到峰值并返回其索引。数组可能包含多个峰值,在这种情况下,返回任 何一个所在位置即可。

1.峰值元素是指其值严格大于左右相邻值的元素。严格大于即不能有等于

2.假设 nums[-1] = nums[n] = 负无穷小

3.对于所有有效的 i 都有 nums[i] != nums[i + 1]

OJ链接【牛客网题号: NC107 寻找峰值】

示例: 输入:[2,4,1,2,7,8,4] 返回值:1

说明:4和8都是峰值元素,返回4的索引1或者8的索引5都可以

输入:[5,3,4,2,6] 返回值:0

说明:-1作为下标或者n下标位置都表示负无穷小, 则0号下标5是峰值,或者4号下标6也是峰值


方法一:

先将数组中首位进行特殊处理,如果满足题中要求直接返回对应下标,如果不满足条件只需要判断数组中当前元素与下一个元素大小即可,如果当前元素大于下一元素则返回当前元素下标即可,反之则继续循环。

int findPeakElement(int* nums, int numsLen ) {
    if (numsLen == 1 || nums[0] > nums[1]) 
        return 0;
    if (nums[numsLen-1] > nums[numsLen-2]) 
        return numsLen-1;
        int a = 0;
    for(int i = 1; i < numsLen-1; i++)
    {
        if(nums[i] > nums[i+1])
        {
            a = i;
            break;
        }
    }
    return a;
}

方法二:

二分思想,中间比右边大,认为从右往左半边递增,则把 right 不断向左靠拢 right=mid ,注意不能是 mid-1 ,因为这个位置有 可能就是峰值点。

直到遇到中间比右边小了,意味着数据开始递降了,则 left 向右偏移, left=mid+1 ; 而一旦 mid+1 位置大于了 right ,意味着刚好这个 mid+1 位置,是一个左半边-右往左递降,右半边-右往左递增的点,就是一个峰值点。

示例: int arr[] = {3, 5, 4, 4, 3, 2, 1} , 这个数组中两边边界都是非峰值点

int left = 0, right = 6;

left=0,right=6,mid=3: arr[3]=4 > arr[4]=3, 则right = mid = 3; //从右往左是递增的 left=0,right=3,mid=1: arr[1]=5 > arr[2]=4, 则right = mid = 1; //从右往左是递增的 left=0,right=1,mid=0: arr[0]=3 < arr[1]=5, 则left = mid + 1 = 1; //从右往左开始递降了

left > right 退出循环, 返回left,也就是1号下标位置。

代码实现:

int findPeakElement(int* nums, int numsLen ) {
    if (numsLen == 1 || nums[0] > nums[1]) 
        return 0;
    if (nums[numsLen-1] > nums[numsLen-2]) 
        return numsLen-1;
    int left = 0, right = numsLen - 1, mid;
    while(left < right) {
        mid = left + (right - left) / 2;
        if (nums[mid] < nums[mid + 1])//中间比右边小,意味着右边肯定有个峰值
            left = mid + 1;
        else //否则在左边包括当前位置肯定有个峰值
            right = mid;
    }
    return left;
}

 以上是本次C语言必会题目,都是些非常经典的内容,希望博主的分享对你们有帮助。

你们的支持是博主最大的动力,谢谢观看!!!文章来源地址https://www.toymoban.com/news/detail-659712.html

到了这里,关于力推C语言必会题目终章(完结篇)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言】指针进阶知识终章

    ✨作者:@平凡的人1 ✨专栏:《C语言从0到1》 ✨一句话:凡是过往,皆为序章 ✨说明: 过去无可挽回, 未来可以改变 🌹 感谢您的点赞与关注,同时欢迎各位有空来访我的 🍁平凡舍 回顾我们前面学习了指针数组、数组指针以及简单介绍了函数指针,传参问题等。下面我们

    2024年02月03日
    浏览(38)
  • Java语言----异常处理(看了必会)

    目录 一.异常的概述 二.异常类的层次结构和种类 二.异常的基本用法 2.1异常的捕捉 2.2异常处理代码实现 三.抛出异常 3.1 throw 3.2 throws 四.finally的进一步详解 五.自定义异常类 总结 😽个人主页:tq02的博客_CSDN博客-C语言,Java领域博主  🌈理想目标:努力学习,向Java进发,拼搏

    2023年04月11日
    浏览(58)
  • 【C语言】初阶完结练习题

     🎈个人主页:库库的里昂  🎐CSDN新晋作者  🎉欢迎 👍点赞✍评论⭐收藏  ✨收录专栏:C语言初阶  ✨其他专栏:代码小游戏  🤝希望作者的文章能对你有所帮助,有不足的地方请在评论区留言指正,大家一起学习交流!🤗 【前言】 C语言初阶 知识点已经全部更完,相

    2024年02月14日
    浏览(44)
  • 详细介绍C语言指针(九千字完结篇)

    本文是指针的完结篇,介绍了函数指针和练习,函数指针数组和计算器的简易实现,认识函数指针数组指针,认识回调函数和qsort排序库函数以及回调函数的使用(模拟实现qsort库函数) 指针初阶篇-指针进阶篇-指针完结篇 在c语言中函数又称子程序,是为了分模块实现各种不同功能而设

    2023年04月13日
    浏览(38)
  • C语言大一期末考试必会编程题

    C语言期末考试必会的编程题,掌握了保证你能不挂科 素数定义: 素数又称质数,是指一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数;比如1,2,3,5,7,9,是素数,4,6,8,10不是素数。 思路: 比如一个数5,判断它是不是素数,就用5依次除以2~4的每

    2024年02月05日
    浏览(45)
  • 【必知必会的MySQL知识】③DML语言

    目录 前言 准备 插入数据 语法格式 插入完整行数据 插入多行数据 将检索出来的数据插入表 更新数据 准备两张表 语法 实践操作 删除数据 语法 实践操作 小结 前面的两篇文章中,我们已经对MySQL有了基本了解。 并且知道了怎么用工具连接数据库?怎么创建数据库?怎么创建

    2024年02月02日
    浏览(64)
  • 【必知必会的MySQL知识】⑤DQL语言

    目录 一、前言 二、基础查询 2.1 语法 2.2 实践操作 三、条件查询 3.1 语法 3.2 where 语句操作符 3.3 实践操作 四、排序查询 4.1 语法格式 4.2 实践操作 五、分组查询 5.1 语法 5.2 聚集函数 5.2.1 聚集函数简单使用 5.3 实践操作 5.4 规定与小结 六、连接查询(多表查询) 6.1 简介 6.2 笛

    2024年02月02日
    浏览(47)
  • 【必知必会的MySQL知识】④DCL语言

    目录 一、概述 二 、授权 2.1 语法格式 2.2 语法说明 2.3 权限类型 2.4 权限级别 三、 回收权限 3.1 语法格式 3.2 语法说明 3.3 注意事项 四 、实践操作 数据控制语言,用来定义访问权限和安全级别。主要包含包括 grant , revoke grant 授予权限 revoke 回收权限 2.1 语法格式 2.

    2024年02月02日
    浏览(43)
  • C语言初学者必学必会的C语言必背100代码

    对于C语言这门计算机语言,算是老生常谈了,现在就由我来给大家分享几个关于C语言的几个代码吧!(如果有错的地方还望见谅) 1.入门级别hello,world #includestdio.h int main() { printf(\\\"Hello,world!n\\\"); return 0; } 2.求素数 #include stdio.h #include math.h int isprime( int n) //n是否是素数 { int i,k=s

    2024年02月08日
    浏览(42)
  • 【C语言必知必会 | 第一篇】C语言入门,这一篇就够了

    引言 C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发。它在编程语言中具有举足轻重的地位。 此文为【C语言必知必会】系列第一篇,带你初步了解C语言,为之后的学习打下基础 C语言起源于美国贝尔实验室的贝尔实验室,由丹尼斯·里奇和肯尼斯

    2024年02月08日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包