【C/C++ 力扣leetcode】4道简单题

news2024/12/23 18:35:09

文章目录

  • 前言
  • 一、寻找正序数组的中位数
    • 中位数的概念
    • C语言版
    • C++版
  • 二、寻找无序数组的中位数
    • 冒泡排序的概念
    • C语言版
    • C++版
  • 三、整数反转
    • 代码实现
    • 原理详解
  • 四、字符串转整数
    • 原理详解
    • 代码实现
  • 总结


前言

刷题之——Leetcode道简单题,通过这4道简单题,C/C++有新的理解,提高你的编程能力。
在这里插入图片描述
leetcode地址


一、寻找正序数组的中位数

中位数的概念

中位数是一组数据中的一个特殊值,可以将这组数据划分为两个部分,其中一部分的数值比中位数小,另一部分的数值比中位数大。换句话说,中位数将数据集合分成了两部分,使得左右两边的数据量相等或差距很小。

在一个有序的数据集合中,中位数就是位于中间位置的值。如果数据集合的个数是奇数,那么中位数就是处于中间位置的那个数;如果数据集合的个数是偶数,那么中位数是中间两个数的平均值。

举个例子,假设有以下一组数据:2, 4, 7, 9, 11。这组数据中共有5个数,是奇数个。中位数就是处于中间位置的那个数,也就是7。

再举个例子,假设有以下一组数据:1, 3, 6, 8, 10, 12。这组数据中共有6个数,是偶数个。中位数就是中间两个数的平均值,(6+8)/2 = 7。

中位数是描述数据集中的典型值,它具有一定的抗干扰能力,因为中位数不受极端值的影响。在统计学、数据分析和排序算法等领域,中位数是一个常用的指标,能够帮助我们更好地了解数据的分布和趋势

C语言版

  • 当为偶数时:n/2的下标数据加n/2-1的下标数据相加除以2就是结果。
  • 当为奇数时:n/2的下标就是结果。

判断奇偶:

  • 当数据个数除以2取余数为0,就是偶数count % 2 == 0
  • 当数据个数除以2取余数为1,就是偶数count % 2 == 1
//nums需要寻找的数组
//size 得到nums数组元素个数 
double findMedianSortedArray(int *nums,int size)
{
	double ret = 0;
		
	/*判断奇偶*/
	if(size % 2 == 0)
	{
		ret += nums[size/2];
		ret += nums[size/2-1];
		ret /= 2;//取平均数
	}
	else
	{
		ret += nums[size/2];
	}
	
	return ret;
}

测试代码如下:

int main()
{
    int vec[5] = {1,2,3,4,5};
    printf("%lf",findMedian(vec,5));

    system("pause");
    return 0;
}

C++版

在C++版本我们可以用vector来替代参数1、2,如下代码:

double findMedian(vector<int> &v) 
{
    double  ret = 0;
    vector<double> tmp = v;
    
    int size = v.size();

    if(size % 2 == 0)//偶数
    {
        ret += tmp.at(size/2-1);
        ret += tmp.at(size/2);
        ret /= 2;
    }
    else
    {
        ret = tmp.at(size/2);
    }

    return ret;
}

在此不用size的原因:vector有成员函数得到数组的大小:vector<type>::size()
测试代码如下:

int main()
{
    vector<int> v{1,2,3,4,5,6};
    cout << findMedian<int>(v) << endl;

    system("pause");
    return 0;
}

在C++中,我们可以使用函数模板tempname <typename T,typename U>来扩大识别范围,扩大函数的使用范围,并且我们可以初始化模板来提高函数的便携性tempname <typename T = int,typename U = double>。代码如下所示:

template <typename T = int,typename U = double>
U findMedian(vector<T> &v) 
{
    U ret = 0;
    vector<T> tmp = v;
    
    int size = v.size();

    if(size % 2 == 0)//偶数
    {
        ret += tmp.at(size/2-1);
        ret += tmp.at(size/2);
        ret /= 2;
    }
    else
    {
        ret = tmp.at(size/2);
    }

    return ret;
}

测试代码如下:

int main()
{
    vector<int> v{1,2,3,4,5,6};
    cout << findMedian(v) << endl;

    system("pause");
    return 0;
}

二、寻找无序数组的中位数

相对于上面的找有序数组,我们无序数组只需要给他排序一下即可放入上面的函数获取结果。
在此我们使用最简单的冒泡排序

冒泡排序的概念

当我们需要对一组数据进行排序时,冒泡排序是一种常用且直观的排序算法。
冒泡排序的原理很简单,类似于我们在冒泡的时候,大的气泡会不断向上升,小的气泡会向下沉一样。
具体步骤如下:

1.首先,我们将待排序的数据分为两部分:已排序部分和未排序部分。
2.然后,从未排序部分的第一个元素开始,通过比较相邻的两个元素的大小,让较大的往后移动,较小的往前移动。这样一轮下来,最大的元素就会像气泡一样浮到了未排序部分的最后面。
3.接下来,重复上述步骤,不断地进行多轮比较和交换,直到所有的元素都按照从小到大的顺序排列好,也就是未排序部分已经变成了空集合。

冒泡排序的核心思想是通过不断比较和交换相邻元素的位置来达到排序的目的。每一轮比较都会让一个最大(或最小)的元素冒泡到正确的位置,所以称之为冒泡排序。
冒泡排序可能在每一轮中都进行多次比较和交换,直到没有需要交换的元素为止。尽管冒泡排序的效率较低,但它非常简单易懂,适用于简单的排序需求或者作为其他排序算法的一部分。

如果不好理解可以看下面视频动画理解:

冒泡排序动画演示

C语言版

冒泡排序实现:

void bubbleSort(int arr[], int size) {
    for (int i = 0; i < size - 1; i++) {
        for (int j = 0; j < size - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                // 交换 arr[j] 和 arr[j+1]
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

在这里我不讲冒泡排序,各位可以直接复制下来。在之后的课程中我会讲到。

double findOutOfOrderMidiean(int *nums,int size)
{
	bubbleSort(nums,size);//调用排序函数
	return findMedianSortedArray(nums,size);//调用寻找中位数函数,并返回
}

C++版

相对于C语言,C++简单多了,不需要写sort函数,因为C++已经提供给我们了。
使用std::sort()函数即可排序头文件为#include <algorithm> using namespace std;
我们只需要放入**vector.begin()vector.end()**即可排序。

排序代码如下:

template <typename T = int,typename U = double>
U findOutOfOrderMidiean(vector<T> &v) 
{
    U ret = 0;
    vector<T> tmp = v;
    sort(tmp.begin(),tmp.end());
    
    return findMedian(tmp);
}

三、整数反转

代码实现

int reverseInteger(int num) {
    int reversed = 0;

    while (num != 0) {
        int remainder = num % 10;
        if (reversed > INT_MAX / 10 || (reversed == INT_MAX / 10 && remainder > 7))
            return 0;
        if (reversed < INT_MIN / 10 || (reversed == INT_MIN / 10 && remainder < -8))
            return 0;
        reversed = reversed * 10 + remainder;
        num /= 10;
    }

    return reversed;
}

原理详解

代码解释如下:
当我们传入一个整数 num 给 reverseInteger 函数时,这段代码的目的是将该整数反转后返回。

1.int reversed = 0;: 创建一个变量 reversed,用于存储反转后的整数,默认值为0。
2.while (num != 0) {: 进入一个循环,只要原始整数不等于0,就会执行循环内的代码。
3.int remainder = num % 10;: 通过取原始整数的末位数字,得到一个变量 remainder,它存储了要添加到反转后整数的数字。
4.if (reversed > INT_MAX / 10 || (reversed == INT_MAX / 10 && remainder > 7)) return 0;: 这个条件判断用于检查反转过程中是否会导致整数溢出。如果反转后的整数 reversed 大于 INT_MAX 的十分之一,或者等于 INT_MAX 的十分之一并且 remainder 大于7(因为反转后的整数乘以10后再加上 remainder,如果大于 INT_MAX 就会溢出),则返回0,表示无法完成反转。
5.if (reversed < INT_MIN / 10 || (reversed == INT_MIN / 10 && remainder < -8)) return 0;: 类似于上一步,这个条件判断用于检查反转过程中是否会导致整数溢出。如果反转后的整数 reversed 小于 INT_MIN 的十分之一,或者等于 INT_MIN 的十分之一并且 remainder 小于-8(因为反转后的整数乘以10后再加上 remainder,如果小于 INT_MIN 就会溢出),则返回0,表示无法完成反转。
6.reversed = reversed * 10 + remainder;: 将原始整数的末位数字 remainder 加到 reversed 的末尾,同时将 reversed 扩大10倍。
7.num /= 10;: 除以10,将原始整数去除末位数字,以便进行下一轮循环。
8.当原始整数的所有位数都被处理完毕(等于0)时,退出循环。
9.return reversed;: 返回反转后的整数 reversed。

这段代码的关键在于通过每次取余和除以10的操作,将原始整数的末位数字逆序地添加到反转后的整数中,直到原始整数的所有位数都被处理完毕。同时,还加入了检查反转过程中是否会导致整数溢出的保护措施。

四、字符串转整数

原理详解

实现技巧:
在我们印象中,只需要实现转换符号和数字部分就可以了,如下图:
在这里插入图片描述
如图的分割线。

但其实我们实现还需要跳过数字前面的空格和不是数字的字符。

1、跳过空格
下列的i为此时的下标

while (str[i] == ' ') {
        i++;
    }

2、处理正负号
我们需要添加一个sign来最后计算最后是否需要添加符号。
原理:正正得正,正负得负,负负得正

int sign = 1;
if (str[i] == '-' || str[i] == '+') {
        sign = (str[i] == '-') ? -1 : 1;
        i++;
    }

3、转换数字:

/*循环条件使其必须是数字才转换*/
while (str[i] >= '0' && str[i] <= '9') {
        result = result * 10 + (str[i] - '0');
        i++;
    }

result = result * 10 + (str[i] - ‘0’);算法解释:
在代码中,result = result * 10 + (str[i] - ‘0’) 的目的是将字符串中的数字字符转换为对应的整数。
str[i] - ‘0’ 的运算实际上是将数字字符转换为对应的数值。在ASCII码中,数字字符的字符编码是连续的,即字符 ‘0’ 的编码是最小的,其后的字符 ‘1’、‘2’、‘3’、… 依次递增。所以,用字符 ‘0’ 的 ASCII 码值减去字符 ‘0’ 的 ASCII 码值,可以得到一个相对的数字值。
例如,对于字符 ‘5’ 而言,‘5’ - ‘0’ 的结果就是整数 5。这是因为 ‘5’ 的 ASCII 码值是 53,而 ‘0’ 的 ASCII 码值是 48,所以 53 - 48 等于 5。
通过将字符转换为数字值,我们可以将每一位的数字逐个添加到 result 中。通过不断乘以10,实现了将新的数字添加到个位、十位、百位等不同的位置上,最终得到整个整数。
例如,对于字符串 “12345”,代码会依次执行以下步骤:

1.result = result * 10 + (str[0] - ‘0’):初始时,result 的值为0,将字符 ‘1’ 转换为整数1,并将其赋值给 result。
2.result = result * 10 + (str[1] - ‘0’):此时,result 的值为1,将字符 ‘2’ 转换为整数2,并将其添加到 result 的十位上。
3.result = result * 10 + (str[2] - ‘0’):此时,result 的值为12,将字符 ‘3’ 转换为整数3,并将其添加到 result 的百位上。
4.result = result * 10 + (str[3] - ‘0’):此时,result 的值为123,将字符 ‘4’ 转换为整数4,并将其添加到 result 的千位上。
5.result = result * 10 + (str[4] - ‘0’):此时,result 的值为1234,将字符 ‘5’ 转换为整数5,并将其添加到 result 的万位上。

所以,通过每次将新的数字乘以10并加到 result 上,最终可以得到反转后的整数值

代码实现

int myAtoi(const char *str)
{
    int result = 0;
    int sign = 1;
    int i = 0;

    // 跳过空格
    while (str[i] == ' ') {
        i++;
    }

    // 处理正负号
    if (str[i] == '-' || str[i] == '+') {
        sign = (str[i] == '-') ? -1 : 1;
        i++;
    }

    // 转换数字
    while (str[i] >= '0' && str[i] <= '9') {
        result = result * 10 + (str[i] - '0');
        i++;
    }

    return result * sign;
}

总结

博主能力有限。可能一些题有更优的做法,不过目前博主是个菜鸟,能做出来就ok了。同时,我们也应该多去总结一下,方便自己的复习的同时,也分享自己的学习过程,这样也挺不错的呀。这次就先到这里结束了,感谢游览。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/745422.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MachineLearningWu_12_BuildNNUsingNumpyOrTF

x.1 咖啡机的例子 我们以煮咖啡为例子来做一个判断煮的咖啡是否符合自己预期的实验。假设煮咖啡的好坏有两个因素决定&#xff0c;温度和煮的时间&#xff0c;图中x表示煮的咖啡很好&#xff0c;o表示煮的咖啡不好&#xff0c;我们根据这个实验来建模&#xff0c;并将模型通过…

简述DHCP服务器获取IP地址的过程

简述DHCP服务器获取IP地址的过程 如何搭建DHCP服务 要在Linux系统上搭建DHCP服务器&#xff0c;你可以按照以下步骤进行操作&#xff1a; 1.安装DHCP服务器软件包&#xff1a; sudo yum install dhcp2.配置DHCP服务器&#xff1a; 打开/etc/dhcp/dhcpd.conf文件&#xff0c…

前向传播之——得分函数

前向传播之-得分函数 1.1 得分函数&#xff1a; 剧透:深度学习必备的两个大知识点分别是前向传播和反向传播啦&#xff0c;这里节课我们会先着手把前方传播的所涉及的所有知识点搞定!我相信这部分对于咱们即便没有什么基础的同学来说也是很容易理解的。 得分函数&#xff1a…

Vue从小白到入门

文章目录 &#x1f34b;Vue是什么?&#x1f34b;MVVM思想 &#x1f34b;vue2快速入门&#x1f34b;注意事项 &#x1f34b;数据单向渲染&#x1f34b;数据双向渲染&#x1f34b;作业布置 &#x1f34b;事件绑定&#x1f34b;事件处理机制&#x1f34b;注意事项和细节&#x1f…

Android屏幕适配方案

方案一&#xff1a; 安卓app禁止跟随系统字体大小&#xff0c;显示大小而改变。 1、定义工具类 public final class DisplayUtil {/*** 禁用7.0&#xff08;23&#xff09;以上显示大小改变和文字大小*/public static Resources disabledDisplayDpiChange(Resources res) {C…

openGauss学习笔记-07 openGauss 语法

文章目录 openGauss学习笔记-07 openGauss 语法7.1 帮助7.2 SQL语句格式7.3 SQL语法ABORTALTER AUDIT POLICYALTER DATA SOURCEALTER DATABASEALTER DEFAULT PRIVILEGESALTER DIRECTORYALTER EXTENSIONALTER FOREIGN TABLEALTER FUNCTIONALTER GROUPALTER INDEXALTER LARGE OBJ…

APB 3

一. APB3概述 APB协议是AMBA总线协议系列的一部分&#xff0c;其接口简单、功耗较低&#xff0c;常用于连接低带宽的高性能外设&#xff0c;每次数据传输至少需要两个时钟周期&#xff0c;且无法同时进行读写操作。 APB作为系统中的从机&#xff0c;可以通过AHB、AHB-Lite、AXI…

RPC分布式网络通信框架(二)—— moduo网络解析

文章目录 一、框架通信原理二、框架初始化框架初始化 三、调用端&#xff08;客户端&#xff09;调用端框架调用端主程序 四、提供端&#xff08;服务器&#xff09;提供端主程序提供端框架NotifyService方法Run方法muduo库的优点网络代码RpcProvider::OnConnection业务代码Rpc…

go 爬虫速度控制

go 爬虫速度控制 使用go语言用原生net/http写爬虫如何优雅的控制并发和请求速度控制并发限流并发和限流的区别简单说明有了并发控制为什么还要限流 最总代码 使用go语言用原生net/http写爬虫如何优雅的控制并发和请求速度 go程序的执行效率相对python要快的多&#xff0c;且占…

如何在半年内找到理想的数据库内核开发工作?

学习和提升技能&#xff1a;着重学习数据库原理、数据结构、算法和数据库内核开发相关的知识。掌握SQL语言和数据库设计&#xff0c;了解常见的数据库系统和底层技术。参加培训、在线课程或自学&#xff0c;不断提升自己的技术能力。 我这里刚好有嵌入式、单片机、plc的资料需…

三、CAS认证流程

一、相关概念 TGC(Ticket-granting cookie)&#xff1a;存放用户身份认证的cookie&#xff0c;在浏览器和CAS server用来明确用户身份的凭证&#xff1b;ST(Service Ticket)&#xff1a;CAS服务器通过浏览器分发给客户端服务器的票据&#xff0c;一个特定服务只能有一个唯一的…

微信小程序开发学习之页面导航(声明式导航和编程式导航)

微信小程序之页面导航&#xff08;声明式导航和编程式导航&#xff09; 1.0 页面导航1.1. 声明式导航1.1.1. 导航到tabBar页面1.1.2. 导航到非tabBar页面1.1.3. 后退导航 1.2. 编程式导航1.2.1. 导航到tabBar页面1.2.2. 导航到非tabBar页面1.2.3. 后退导航 1.3. 导航传参1.3.1.…

手把手教你用 NebulaGraph AI 全家桶跑图算法

前段时间 NebulaGraph 3.5.0 发布&#xff0c;whitewum 吴老师建议我把前段时间 NebulaGraph 社区里开启的新项目 ng_ai 公开给大家。 所以&#xff0c;就有了这个系列文章&#xff0c;本文是该系列的开篇之作。 ng_ai 是什么 ng_ai 的全名是&#xff1a;Nebulagraph AI Sui…

安装RabbitMQ 详细步骤

我这里是在Linux系统里面安装的按照步骤即可 1. 安装Socat&#x1f349; 在线安装依赖环境&#xff1a; yum install gcc yum install socat yum install openssl yum install openssl-devel2. 安装Erlang&#x1f349; 去官网下载一下安装包&#xff0c;将安装包拉到Linux系…

苹果APP安装包ipa如何安装在手机上

苹果APP的安装比安卓复杂且困难&#xff0c;很多人不知道如何将ipa文件安装到手机上。以下是几种苹果APP安装在iOS设备的方式&#xff0c;供大家参考。 一、上架App Store 这是最正规的方式。虽然审核过程复杂、时间较长&#xff0c;且审核条件较为苛刻&#xff0c;但借助第三…

【UE C++】蓝图调用C++函数

目录 一、蓝图调用其继承的C类的函数 二、蓝图调用全局C函数 一、蓝图调用其继承的C类的函数 首先新建一个C类 父类选择“Actor” 这里命名为“MyActorFromC”&#xff0c;然后点击创建类&#xff0c;等待编译完成。 在头文件中申明函数 UFUNCTION(BlueprintCallable, Categ…

list分段截取方法

对list 分段截取方法是一个常见的操作&#xff0c;通常用于对list数据批量操作&#xff0c;常见的场景有返回分页展示数据&#xff0c;对大数据进行分批次插入数据库等 package com.hmdp.dto;import org.apache.commons.collections4.ListUtils; import org.springframework.u…

Golang学习——string和slice切片

Golang学习——string和slice切片 string整数存储字符存储Unicode存储变长编码规则字符串类型变量的结构字符串变量的修改方式 slice通过make的方式定义变量new底层数组slice扩容规则1.预估扩容后的容量newCap2.newCap个元素需多大内存3.匹配到合适的内存规格练习 string 整数…

如何进行高效的日程管理?

在日程安排逐渐增多的现代职场中&#xff0c;如果想要高效完成工作事项&#xff0c;就必须做好每天的日常管理。但是有不少上班族表示自己在做日程管理时往往感到力不从心&#xff0c;很难做到真正有效的管理自己的日程安排&#xff0c;那么问如何进行高效的日程管理呢&#xf…

利用Python数据挖掘技术深入理解股票回撤的本质

股票回撤是投资者关注的一个重要指标&#xff0c;也是进行风险评估和投资决策的必要依据。通过利用Python数据挖掘技术深入理解股票回撤的本质&#xff0c;可以更加准确地评估风险和制定投资策略。 一、什么是股票回撤 股票回撤是指股票价格在上涨过程中出现暂时的下跌&#…