分治法——找众数

分治法——找众数

要求:

寻找整数数组的众数,如果存在多个众数,则返回权值最小的那个


第一步:

要利用分治法找众数,首先就先要使数组有序。这里,我们用C语言库中的qsort进行快排:

qsort(nums, numsSize, sizeof(int), cmp_int);
//nums——给定数组
//numsSize——数组大小
//cmp_int——qsort要用到的函数指针

第二步:

开始编写分治算法,寻找众数。

函数声明:

void Find_Mode(int* nums, int begin, int end)

为了方便,我们先定义两个全局变量mode_countmode_index来记录众数出现的次数和下标

int mode_count = 0;	//记录众数出现的次数
int mode_index = 0;	//记录下标

我们以下面的有序数组为例:

在这里插入图片描述

  • 首先假设众数为数组中间的数,记其下标为mode

    int left = begin;
    int right = end;
    int mode = (right - left) / 2 + left;	//为防止整形移除,故不采用(right + left)/2的写法
    
  • 然后,移动leftright,确定有多少个值为nums[mode]的元素:

    while (left < right && nums[left] != nums[mode])
        left++;
    while 
        (left < right && nums[right] != nums[mode])
        right--;
    
    //这样,值为nums[mode]的元素个数为(right - left + 1)
    

    在这里插入图片描述

  • 当确定好nums[mode]的个数count后,就需要比较[begin, left - 1][right + 1, end]这两个区间的和count的大小

    • 如果[begin, left - 1]区间的大小大于或等于count就说明该区间内可能出现出现次数更多的或者权值更小的众数。因此要继续进行递归分治
    • 对于区间[right + 1, end]同理。
    if (left - begin >= right - left + 1)
        Find_Mode(nums, begin, left - 1);
    
    if (end - right >= right - left + 1)
        Find_Mode(nums, right + 1, end);
    
  • 如果上面两个if语句没有执行,那就说明nums[mode]出现的次数count就是最大的,那就需要和mode_count(众数出现的次数)进行比较

    • 如果count == mode_count。那就比较nums[mode]nums[mode_index]的权值,并将众数更新为权值较小的那个,并更新mode_index
    • 如果count > mode_count。那就直接让众数为nums[mode],更新mode_countmode_index
    • 如果count < mode_cout。就不做任何修改
    //right - left + 1即上文所说的count
    if (mode_count <= right - left + 1)
    {
        //如果二者相等,就取权值较小的
        if (mode_count == right - left + 1)
            mode_index = nums[mode] < nums[mode_index] ? mode : mode_index;
        else
        {
            mode_index = mode;
            mode_count = right - left + 1;
        }
    }
    
  • 函数整体即为:

    int mode_count = 0;	//记录众数出现的次数
    int mode_index = 0;	//记录下标
    
    void Find_Mode(int* nums, int begin, int end)
    {
        int left = begin;
        int right = end;
        int mode = (right - left) / 2 + left;
    
        //移动做右指针,寻找nums[mode](假设的众数)的出现次数
        while (left < right && nums[left] != nums[mode])
            left++;
        while (left < right && nums[right] != nums[mode])
            right--;
        
        //如果左右区间的长度大于或者等于nums[mode](假设的众数)的出现次数
        //那就进行分治递归
        if (left - begin >= right - left + 1)
            Find_Mode(nums, begin, left - 1);
        
        if (end - right >= right - left + 1)
            Find_Mode(nums, right + 1, end);
    
        //更新众数
        if (mode_count <= right - left + 1)
        {
            //如果二者相等,就取权值较小的
            if (mode_count == right - left + 1)
                mode_index = nums[mode] < nums[mode_index] ? mode : mode_index;
            else
            {
                mode_index = mode;
                mode_count = right - left + 1;
            }
        }
    }
    

整体代码:

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

int mode_count = 0;	//记录众数出现的次数
int mode_index = 0;	//记录下标

void Find_Mode(int* nums, int begin, int end)
{
    int left = begin;
    int right = end;
    int mode = (right - left) / 2 + left;

    //移动做右指针,寻找nums[mode](假设的众数)的出现次数
    while (left < right && nums[left] != nums[mode])
        left++;
    while (left < right && nums[right] != nums[mode])
        right--;
    
    //如果左右区间的长度大于或者等于nums[mode](假设的众数)的出现次数
    //那就进行分治递归
    if (left - begin >= right - left + 1)
        Find_Mode(nums, begin, left - 1);
    if (end - right >= right - left + 1)
        Find_Mode(nums, right + 1, end);

    //更新众数
    if (mode_count <= right - left + 1)
    {
        //如果二者相等,就取权值较小的
        if (mode_count == right - left + 1)
            mode_index = nums[mode] < nums[mode_index] ? mode : mode_index;
        else
        {
            mode_index = mode;
            mode_count = right - left + 1;
        }
    }
}

//qsort需要的函数
int cmp_int(void const* num1, void const* num2)
{
	return *(int*)num1 - *(int*)num2;
}

int main()
{
	int nums[] = { 10, 4, 2, 10, 5, 8, 9, 5, 6, 1, 4, 7, 2, 1, 7, 4, 3, 1, 7, 2 };
	int numsSize = sizeof(nums) / sizeof(int);

	qsort(nums, numsSize, sizeof(int), cmp_int);	//利用快速排序排序数组,是数组升序排列

	Find_Mode(nums, 0, numsSize - 1);	//找众数

	printf("众数为:%d\n", nums[mode_index]);

	return 0;
}

注:本题已通过牛客网[编程题]众数验证正确性。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

3D高斯泼溅(Splatting)简明教程

在线工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 3D场景编辑器 3D 高斯泼溅&#xff08;Splatting&#xff09;是用于实时辐射场渲染的 3D 高斯分布描述的一种光栅化技术&#xff0c;它允许实时渲染从小图像样…

直流无刷电机(BLDC)六步换相驱动

直流无刷电机&#xff08;BLDC&#xff09;六步换相驱动 文章目录 直流无刷电机&#xff08;BLDC&#xff09;六步换相驱动1. 前言2. 六步换相原理3. 电角度与机械角度4. 动手实践4.1 霍尔输出表测量4.2 换向控制4.3 代码编写 5. 总结 1. 前言 直流无刷电机相对直流有刷电机具…

Redis之Java操作Redis的使用

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《Redis实战开发》。&#x1f3af;&#x1f3af; …

Android java Handler sendMessage使用Parcelable传递实例化对象,我这里传递Bitmap 图片数据

一、Bundle给我们提供了一个putParcelable(key,value)的方法。专门用于传递实例化对象。 二、我这里传递Bitmap 图片数据&#xff0c;实际使用可以成功传统图像数据。 发送&#xff1a;Bundle bundle new Bundle();bundle.putParcelable("bitmap",bitmap);msg.setD…

【GitLab CI/CD、SpringBoot、Docker】GitLab CI/CD 部署SpringBoot应用,部署方式Docker

介绍 本文件主要介绍如何将SpringBoot应用使用Docker方式部署&#xff0c;并用Gitlab CI/CD进行构建和部署。 环境准备 已安装Gitlab仓库已安装Gitlab Runner&#xff0c;并已注册到Gitlab和已实现基础的CI/CD使用创建Docker Hub仓库&#xff0c;教程中使用的是阿里云的Docker…

【漏洞复现】Apache_Tomcat7+ 弱口令 后台getshell漏洞

感谢互联网提供分享知识与智慧&#xff0c;在法治的社会里&#xff0c;请遵守有关法律法规 文章目录 1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现1、基础环境2、漏洞扫描3、漏洞验证 说明内容漏洞编号漏洞名称Tomcat7 弱口令 && 后台getshell漏洞漏洞评级高…

【Java】Beanshell下通过java操作Excel(xlsx格式)文件读写

一、概述 在项目开发中往往需要使用到Excel的导入和导出,导入就是从Excel中导入到DB中,而导出就是从DB中查询数据然后使用POI写到Excel上。 操作Excel目前比较流行的就是Apache POI和阿里巴巴的easyExcel ! Excel文件处理的主流技术包括: Apache POI 、 JXL 、 Alibaba Ea…

机器学习---SVM目标函数求解,SMO算法

1. 线性可分支持向量机 1.1 定义输入数据 假设给定⼀个特征空间上的训练集为&#xff1a; 其中&#xff0c;(x , y )称为样本点。 x 为第i个实例&#xff08;样本&#xff09;。 y 为x 的标记&#xff1a; 当y 1时&#xff0c;x 为正例&#xff1b;当y −1时&#xff0c;x…

16. 机器学习 - 决策树

Hi&#xff0c;你好。我是茶桁。 在上一节课讲SVM之后&#xff0c;再给大家将一个新的分类模型「决策树」。我们直接开始正题。 决策树 我们从一个例子开始&#xff0c;来看下面这张图&#xff1a; 假设我们的x1 ~ x4是特征&#xff0c;y是最终的决定&#xff0c;打比方说是…

合肥中科深谷嵌入式项目实战——人工智能与机械臂(六)

订阅&#xff1a;新手可以订阅我的其他专栏。免费阶段订阅量1000 python项目实战 Python编程基础教程系列&#xff08;零基础小白搬砖逆袭) 说明&#xff1a;本专栏持续更新中&#xff0c;订阅本专栏前必读关于专栏〖Python网络爬虫实战〗转为付费专栏的订阅说明作者&#xff1…

Python最强自动化神器Playwright!再也不用为爬虫逆向担忧了!

版权说明:本文禁止抄袭、转载,侵权必究! 目录 一、简介+使用场景二、环境部署(准备)三、代码生成器(优势)四、元素定位器(核心)五、追踪查看器(辅助)六、权限控制与认证(高级)七、其他重要功能(进阶)八、作者Info一、简介+使用场景 Playwright是什么?来自Chat…

0001Java安卓程序设计-基于Android多餐厅点餐桌号后厨前台服务设计与开发

文章目录 **摘** **要****目** **录**系统设计开发环境 编程技术交流、源码分享、模板分享、网课教程 &#x1f427;裙&#xff1a;776871563 摘 要 移动互联网时代的到来&#xff0c;给人们的生活带来了许多便捷和乐趣。随着用户的不断增多&#xff0c;其规模越来越大&#…

linux环境下编译,安卓平台使用的luajit库

一、下载luajit源码 1、linux下直接下载&#xff1a; a、使用curl下载&#xff1a;https://luajit.org/download/LuaJIT-2.1.0-beta3.tar.gz b、git下载地址&#xff1b;https://github.com/LuaJIT/LuaJIT.git 2、Windows下载好zip文件&#xff0c;下载地址&#xff1a;https…

【四、http】go的http的文件下载

一、日常下载图片到本地 //下载文件func downloadfile(url, filename string) {r, err : http.Get(url)if err ! nil {fmt.Println("err", err.Error())}defer r.Body.Close()f, err : os.Create(filename)if err ! nil {fmt.Println("err", err.Error())…

一文详解:传统企业如何把进销存管理流程搬到线上?

进销存管理是企业管理的核心流程之一&#xff0c;它有助于提高效率、降低成本、增加盈利&#xff0c;同时确保客户满意度&#xff0c;这对于企业的长期成功和竞争力至关重要。但在信息化转型的浪潮下&#xff0c;很多企业的传统进销存流程却遇到不少问题。 如果你也在考虑把进…

Navicat连接mysql 8.0.35 2059错误解决办法

这2天在家重装电脑&#xff0c;顺便把mysql升级8.0&#xff0c;安装完成后&#xff0c;用Navicat连接&#xff0c;报错2059&#xff0c;如下 网上查了一下&#xff0c; 【报错原因】mysql8.0 之前的版本中加密规则是 mysql_native_password&#xff0c;而 mysql8.0 之后的版本…

随机微分方程的分数扩散模型 (score-based diffusion model) 代码示例

随机微分方程的分数扩散模型&#xff08;Score-Based Generative Modeling through Stochastic Differential Equations&#xff09; 基于分数的扩散模型&#xff0c;是估计数据分布梯度的方法&#xff0c;可以在不需要对抗训练的基础上&#xff0c;生成与GAN一样高质量的图片。…

【Kotlin精简】第7章 泛型

1 泛型 泛型即 “参数化类型”&#xff0c;将类型参数化&#xff0c;可以用在类&#xff0c;接口&#xff0c;函数上。与 Java 一样&#xff0c;Kotlin 也提供泛型&#xff0c;为类型安全提供保证&#xff0c;消除类型强转的烦恼。 1.1 泛型优点 类型安全&#xff1a;通用允许…

CoDeSys系列-4、基于Ubuntu的codesys运行时扩展包搭建Profinet主从环境

CoDeSys系列-4、基于Ubuntu的codesys运行时扩展包搭建Profinet主从环境 文章目录 CoDeSys系列-4、基于Ubuntu的codesys运行时扩展包搭建Profinet主从环境一、前言二、资料收集三、Ubuntu18.04从安装到更换实时内核1、下载安装Ubuntu18.042、下载安装实时内核&#xff0c;解决编…

如何将PDF文件转换成翻页电子书?这个网站告诉你

​随着电子书的普及&#xff0c;越来越多的人开始将PDF文件转换成翻页电子书。翻页电子书不仅方便阅读&#xff0c;而且还可以在手机上轻松翻页。那么如何将PDF文件转换成翻页电子书呢&#xff1f;今天就为大家介绍一个网站&#xff0c;可以帮助你轻松完成这个任务。 1.首先&am…