AcWing 52. 数组中出现次数超过一半的数字(基于中位数和众数的线性复杂度的解法)

蓝桥杯C++B组省赛深度复盘:从DFS剪枝到矩阵快速幂的解题精要 深度优先搜索(DFS)和广度优先搜索(BFS)是算法竞赛中解决组合优化与路径规划问题的两大核心搜索技术。DFS通过递归探索所有可能分支,常需结合剪枝策略(如最优性剪枝)来避免无效搜索,提升效率;BFS则通过队列实现层序遍历,是求解无权图最短路径的标准方法。在工程实践中,这些算法是解决迷宫寻路、状态空间搜索等问题的利器。本文以蓝桥杯经典赛题为载体,深入剖析了DFS剪枝在“组队”问题中的应用,以及BFS在“迷宫”最短路径记录中的实现细节,展示了如何将基础算法灵活运用于复杂场景,并规避常见陷阱。 阅读详情

 这道题最直观的解法就是使用排序算法将数组变为一个有序数组。显然,满足题意的数字必然是此时数组的中位数。但是,我们仍然清楚,即使是最快的排序算法,复杂度也不能低于O(nlogn)。不过,以下两个方法都可以在线性复杂度内解决此问题。

1.基于快速排序的轴点选择函数的算法(中位数)

快速排序的轴点选择函数会将序列中小于轴点值的数值放置到轴点左侧,大于等于轴点值的数值放置到轴点右侧。我们令每一次划分后都返回轴点所在的位置。如果说这个轴点的位置恰好为中位数,则直接输出。如果在轴点位置在中位数左侧则说明目标数值不可能出现在轴点位置左侧,需要对右侧部分重新进行划分。轴点位置在中位数右侧则同理对左侧部分重新进行划分。直至轴点位置恰好为中位数的位置。

具体代码如下:

class Solution {
public:
    int partition(vector<int> &nums, int lo, int hi){
        int i = lo, j = hi;
        while(i < j){
            while(nums[i] < nums[lo]) i++;
            while(nums[j] >= nums[lo]) j--;
            if(i < j) swap(nums[i], nums[j]);
        }
        swap(nums[i], nums[lo]);
        return i;
    }

    int moreThanHalfNum_Solution(vector<int>& nums) {
        int lo = 0, hi = nums.size() - 1;
        int mid = nums.size() >> 1;
        int index = partition(nums, lo, hi);
        while(index != mid){
            if(index > mid){
                hi = index - 1;
                index = partition(nums, lo, hi);
            }
            else{
                lo = index + 1;
                index = partition(nums, lo, hi);
            }
        }
        return nums[mid];
    }
};

此算法的时间复杂度为O(n),空间复杂度为O(1)。另外,此算法会改变原数组。

2.基于统计的算法(众数)

可以发现,满足条件的数字同时也是所有数字中的众数。那么我们可以统计数字的出现次数从而决定哪个数字是符合题意的。当然,这是最原始的方法。然而很多人不愿意使用的原因在于,为了做出相应的统计需要额外开辟空间用来记录。同时哈希表自身的查找也要耗费可观的时间。

不过,我们没有必要统计所有数的出现次数。因为我们要找的是出现次数最多的那个数,因此可以采取如下的方法。

首先我们维护两个变量,一个用来存放当前已遍历序列中出现次数最多的数,另一个用来记录这个数值相对于其他已遍历数值多出的出现次数。对于每一个当前扫描到的数,如果其值等于维护的数值则次数加1,反之则减1。当次数变为0时则将当前数字替换为新的维护数字。这样直至遍历结束,最后一个令次数记为1的数字就是最终结果。

具体代码如下:

class Solution {
public:
    int moreThanHalfNum_Solution(vector<int>& nums) {
        int ans = nums[0], count = 1;
        for(int i = 0; i < nums.size(); i++){
            if(ans == nums[i]) count++;
            else{
                count--;
                if(!count){
                    ans = nums[i];
                    count = 1;
                }
            }
        }
        return ans;
    }
};

此算法的时间复杂度为O(n),空间复杂度为O(1)。另外,此算法不会改变原数组。

TOD和PPS精确时间同步技术 授时 阅读详情

相关推荐

CST毫米波雷达ADAS仿真:从直角反射器到距离多普勒(RD图)的实战解析

本文通过CST Studio Suite实战解析毫米波汽车雷达ADAS仿真,详细演示了从构建直角反射器目标、参数化定义速度、进行参数扫描到生成距离多普勒图(RD图)的全过程。文章深入探讨了雷达关键参数(如距离分辨率、速度分辨率)的设计权衡与工程逻辑,并提供了单位统一、速度范围设定等实用避坑指南,帮助工程师高效完成雷达系统性能的前期验证与优化。

weixin_29292535的博客 502

十分钟学算法-快速排序

//2.快速排序(QuickSort) /* 本质:冒泡排序基础上的递归分治法。 2.1算法描述 1.数列挑出一元素(“基准”pivot) 2.分区操作(partition):所有比基准小的放在基准前面;比基准大的放后面 3.递归地(recursive)把小于基准元素和大于基准元素的子数列排序 2.2 最好||平均时间复杂度O(nlogn)//以2为底 不稳定排序算法 */ /* 分组操作 对一组区间为[m,n]数据进行分组操作...

qq_44985236的博客 886

Python实现高光谱图像生成与增强:从RGB到多光谱转换(附完整代码)

本文分享一个基于Python的实用工具,能够将普通RGB图像转换为模拟高光谱图像,并进一步生成增强的彩色可见图像。为了直观展示图像细节,程序通过对特定波段的组合,生成了一幅增强的 RGB 彩色图像。该函数的主要目标是将一张普通的 RGB 图像转换为包含多个波段的高光谱图像。通过该函数,我们能直观地看到高光谱图像经过波段组合后所得到的彩色图像效果。通过以上代码,我们可以实现对海量图像数据的自动化处理,极大地提升工作效率。已附在文中,欢迎下载测试!通过以上步骤,我们可以生成一幅包含多个光谱波段信息的图像。

m0_74824642的博客 3666

面试题39. 数组中出现次数超过一半的数字、数组中出现次数最多的元素

题目 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 输出: 2 限制: 1 <= 数组长度 <= 50000 解题方法 本题可选择哈希映射:构建键值对的方法来实现。 我们可以使用哈希映射来解决这个问题,把数值作为键,把数值出现的...

Tiger数学之家的博客 320

VBA学习笔记6:将多个工作表中满足条件的数据汇总到同一个工作表

VBA学习笔记6:将多个工作表中满足条件的数据汇总到同一个工作表

weixin_45355881的博客 4708

知识图谱实战应用8-从文本关系抽取到知识图谱关系构建流程贯通

大家好,我是微学AI,今天给大家介绍一下知识图谱实战应用8-从文本关系抽取到知识图谱关系构建流程贯通。我们从文本数据中采集到关键信息,并抽取出其中的关系信息,然后在存入图数据库中,整个过程实现自动化,我这里将举一个文本例子进行抽取。 对于知识图谱的构建是将实体、概念和它们之间的关系都以图表形式呈现出来的一种数据结构。要构建一个知识图谱,需要从不同的数据源中采集到相关信息,并将这些信息整合在一起,最终形成一个全面而且精确的知识图谱。

微学AI的博客 2545

找出数组中元素出现次数超过数组长度一半的元素

题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。 这道题有多种解法,下面主要说两种。 常规方法:创建一个Map,遍历数组中的元素,如果元素不在map中出现过,将元素设置为key,value=1,如果元素在map中,就取出这个元素,并将对应的value值+1.最后遍历map中的元素,如果有value>数组长度的一半,就返回值 思维方

一李 1020

【零基础入门unity游戏开发——unity通用篇12】导入导出unity资源包、设置编程工具、创建脚本(组件)规则、MonoBehaviour基类介绍、脚本模板(基于unity6开发介绍)

导入导出unity资源包、设置编程工具、创建脚本(组件)规则、MonoBehaviour基类介绍、脚本模板(基于unity6开发介绍)

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 760

找出数组中出现次数超过一半的数

如果有一个数出现的次数超过一半,那他出现的次数肯定比其他数字出现次数的和还要多,这时可以遍历数组并保存两个值,一个是出现的数字,一个是次数,当下一个数字和保存的数字相同时,次数加1,如果不同,次数减1,如果次数为0,我们需要保存下一个数字,并将次数设为1。最后保存的数字即为所求。同时考虑空数组和没有出现次数超过一半的情况。 class Solution { public: int Mor

菜鸡 909

微信小程序——01开发前的准备和开发工具

微信小程序——01开发前的准备和开发工具

总裁余(余登武)博客 1万+

【PPS便携式移动电源】如何透彻了解便携式移动电源,仅需要十分钟阅读即可

PPS 便携式储能电源的发展前景广阔,受益于户外经济爆发、应急备灾需求提升及 “双碳” 政策支持,全球市场规模预计持续增长,2025 年出货量将达 2380 万台,未来将向大功率大容量、光充一体化、智能化方向发展,还会拓展家庭储能、移动医疗等新场景,同时钠离子电池应用、双向逆变技术升级将进一步推动行业发展。

昔时扬尘处 272

【算法】线性排序

  前面提到的几种排序最优的时间复杂度为O(nlog n),但在排序算法中还不是最优的,有几种算法的时间复杂度为O(n),因为时间复杂度是线性的,所以又称线性排序。他们有桶排序、计数排序、基数排序,之所以能够达到线性的时间复杂度,是因为他们都不涉及元素之间的比较操作,这就意味着他们的使用条件都比较苛刻。 桶排序   桶排序主要原理就是将要排序的数据分别分到几个桶里面,然后每个桶里...

aoaichen0637的博客 168

把数据库事务边界握在手里:ABAP 里的 COMMIT CONNECTION 与 ROLLBACK CONNECTION 深度拆解

与表面是两条很短的语句,背后却牵动了连接管理、数据库 LUW、SAP LUW、隐式提交、游标生命周期、GTT 平台差异等一整片工程现实。把它们用对,你就能在不破坏主业务事务的前提下,实现跨库写入、审计落库、隔离型日志、数据集成落地等一系列“看似矛盾”的目标;用错了,它们也会悄无声息地制造一致性缺口,让问题在高峰期以 dump 或数据异常的方式爆出来。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1841

AcWing 53. 最小的k个数(堆+快速排序的轴点选择函数)

1.基于堆的实现 创建一个最大堆,控制其最大规模为k。若堆的规模小于k则不断将数组元素压入到堆中,否则则要根据当前元素和堆顶元素的大小来判断是否进行“交换”操作(堆顶元素弹出,当前数组元素压入)。不断重复此操作就可以将原数组中所有最小的k个数全部保留到堆中了。 具体代码如下: class Solution { public: vector<int> getLeast...

Zee_Chao的博客 308

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

线性时间的中位数查找算法

原帖链接 一、以期望线性时间做选择 一般来说,中位数的查找算法都是基于先排序,后找中间位置的数字的算法,但是因为线性时间排序所收到的限制比较大,而如果使用基于比较的排序,时间复杂度将至少为O(nlogn),如何以线性时间完成中位数或者数组中第N大元素的查找呢? 快速排序算法在每一次局部递归后都保证某个元素左侧的元素都比他小,右侧的元素都比她大,因此,可以利用这个思路快速找

Learn as if you were to live forever 1万+

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

找到数组中出现次数超过数组长度一半的元素

题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字,否则返回0。比如长度为9的数组{1,2,3,2,2,2,5,4,2},数组中2出现了5次,超过数组长度的一半,因此输出2。 方法1:因为这个数字超过了数组长度的一半,所以,我首先想到的是将数组排序,排序后中间的元素就是我们要找的数据,然后再判断它出现的次数是不是超过了数组长度的一半。 #include &amp;amp;lt;algorith...

Cheng_913的博客 7023

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

数据结构与算法-- 数组中出现次数超过一半的数字(时间复杂度的讨论)

时间效率 互联网想对时间效率格外的敏感,所以我们总是在需求迭代一定程度后去做优化。而且我们解决问题的时候,时间效率往往是一个考查的重点。因此我们平时编码过程中就必须不断的优化效率,追求完美的态度与能力。 首先是编码习惯,例如java中字符串操作我们不建议使用String的+ 运算符来完成。这样会产生非常多的String临时变量,造成空间与实际的浪费,更好的方式是用StringBuilder的Append方法完成字符串的拼接。 其次,即使是同一个算法用循环和递归两种思路实现时间效率也是不一样的。递归的本质

0102的博客 476

剑指Offer-29-java实现查找数组中出现次数超过一半的元素

思路: 数组中有一个数字出现的次数超过数组长度的一半,也就是说它出现的次数比其他所有数字出现次数的和还要多。 因此我们可以考虑在遍历数组的时候保存两个值: 一个是数组中的一个数字, 一个是次数。当我们遍历到下一个数字的时候,如果下一个数字和我们之前保存的数字相同,则次数加1:如果下一个数字和我们之前保存的数字,不同,则次数减1 。如果减1之后,此时次数为零,我们需要保存下一个数字,并把次数设为

nwpu_geeker的博客 2009

洛谷p1056排座椅

错误代码: #include<iostream> #include<cstring> using namespace std; char s[15][15];//存储读进来的字符串 int a[15][15];//起始格标号,不是起始格的标号为0,黑格标号为-1 int visit[15][15]; int main() { int kase = 0; int r, ...

放浪曲蘖的博客 224

leetcode 73 数组中出现次数超过一半的数字:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。python

NC73 数组中出现次数超过一半的数字: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。你可以假设数组是非空的,并且给定的数组总是存在多数元素。1<=数组长度<=50000 两种思路。第一种思路,出现次数超过一半的数字,不管如何,必然这个数字位于数组中间的位置,因此可以采用类似于快排的划分的方法,找到位于数组中间的位置的数字,然后在顺序检索是否这个数字出

q339179198的博客 419

数据结构与算法——在O(n)的时间复杂度内找出数组中出现次数超过了一半的数

如何在O(n)的时间复杂度内找出数组中出现次数超过了一半的数 方法一:hash法 首先创建一个hash_map,其中,key为数组元素值,value为此数出现的次数。遍历一遍数组,用hash_map统计每个数出现的次数,并用两个值存储目前出现次数最多的数和对应的次数,此时的时间复杂度为O(n),空间复杂度为O(n) 方法二 如果每次删除两个不同的数,那么在剩余的数字里,原出现次数最多的数出现的频率一样超过了50%,不断重复这个过程,最后剩下的将全是同样的数字。具体实现为: 使用两个变量A和B,其中变量A存储

beilizhang的博客 460

排序和查找-线性排序算法和查找特定值

一、排序算法的时间下界 常用排序算法中的冒泡排序、选择排序、插入排序等排序算法都是基于比较的。对于基于比较的排序算法,其时间下界为Ω(nlgn). 用决策树模型可以证明该结论。基于比较的排序算法的每一次排序都可以看做是一次决策,决策的结果是比较的两个值是大于或者小于等于。考虑三个元素的排序,以下标表示每个元素,我们可以构造如下的决策树: 图中的每个非页节点表示要比较的两个元素的下标,

浩海拾贝 2730

线性时间查找数量超过数组长度一半的数

期望线性时间查找数量超过数组长度一半的数思路分析事实上,数量超过数组长度(n)一半的数也就是数组中第n/2大的数。 这道题如果不限制时间复杂度,brute force(通过排序)查找的时间复杂度可达到O(nlogn)O(n\log n)。为了找到更快的算法,我们可以借用快速排序中的partition函数。每次运行partition函数,某一组数的pivot都能被放在最终的位置上。假设这个pivot

rose_gong的专栏 714

出现次数超过一半的数字

题目描述 题目:数组中有一个数字出现的次数超过了数组长度的一半,找出这个数字。 分析与解法 一个数组中有很多数,现在我们要找出其中那个出现次数超过总数一半的数字,怎么找呢?大凡当我们碰到某一个杂乱无序的东西时,我们人的内心本质期望是希望把它梳理成有序的。所以,我们得分两种情况来讨论,无序和有序。 解法一 如果无序,那么我们是不是可以先把数组中所有这些数字先进行排序(至

qisefengzheng的专栏 总有一天你将破蛹而出 895

AcWing 34. 链表中环的入口结点(快慢指针赛跑+地址映射)

1.快慢指针赛跑 这是一个做起来很巧妙的算法,而且这个方法既不会改变原链表的结构,又不会需要额外的空间。 具体的操作是:从头结点开始,令快指针每次移动两个单位,慢指针每次移动一个单位。如果链表有环则两个指针必定会在环上的某一个位置相遇。此时令快指针重回起点,然后让两个指针同时每次移动一个单位,当两个指针再次相遇时(必定会相遇),相遇的结点恰好就是环的入口结点。 证明如下: 假设链表...

Zee_Chao的博客 1493

AcWing解题目录(C++)

# 试题名称 思想方法 难度 试题来源 1 A+B 简单 AcWing 2 01背包问题 简单 3 完全背包问题 简单 4 多重背包问题I 简单 5 多重背包问题II 中等 6 多重背包问题...

Zee_Chao的博客 900
上一篇: AcWing 51. 数字排列(DFS(有重复排列+无重复排列))
下一篇: AcWing 53. 最小的k个数(堆+快速排序的轴点选择函数)
Zee_Chao
博客等级 码龄11年 168粉丝 135原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值