数组中的主要元素

leetcode#169题,找出一个数组中出现次数超过

次数的元素,也就是过半的主要元素。题目来源:

https://leetcode.com/problems/majority-element/

解题思路

哈希表

遍历一次数组然后将每个元素出现的次数放在哈希表中,key是元素,value是出现的次数。然后输出哈希表中值大于

的元素。

复杂度

遍历数组的时间复杂度为O(n),新建一个哈希表造成的空间复杂度为O(n)。

代码

第一个是自己写的,输入是为了自己调试和算法课程作业的UOJ,这个OJ有个卡内存的坑后面讲。

#include<iostream>
#include<vector>
#include<map>
#include <stdio.h>using namespace std;
class Solution {public:int majorityElement(vector<int>& nums) {map<int, int> m;for(int i=0; i<nums.size(); i++){m[nums[i]]++;}int major = 0;int max = 0;for(map<int, int>::iterator it= m.begin(); it!=m.end(); it++){if(it->second>=max){max = it->second;major = it->first;}}return major;}
};int main(int argc, char const *argv[])
{// Solution sol;// std::vector<int> vec={3,2,3};// int ans = sol.majorityElement(vec);// cout<<ans<<endl;// cin>>ans;ios::sync_with_stdio(false);int len;Solution Sol;int ans;while(cin>>len){vector<int> vec(len);for(int i = 0; i < len; i++) {cin>>vec[i];}ans = Sol.majorityElement(vec);cout<<ans<<endl;}return 0;
}

然后再来看看花花大神写的:

// Author: Huahua
// Runtime : 23 ms
class Solution {public:int majorityElement(vector<int>& nums) {unordered_map<int, int> count;const int n = nums.size();for (const int num : nums)if (++count[num] > n / 2) return num;return -1;}
};

我自己写的代码多了一步冗余操作,就是完整的把count哈希表给建立完毕之后又多次一举的进行遍历寻找最大值。实际上在对原来的数组进行遍历的同时一定会出现主要元素的计数大于

,这个时候直接返回就可以了。

分治

首先考虑最简单的情况,当n=1的时候,这个唯一的元素就是主要元素,这是一个最简单的子问题。那么是否所有自问都能正确返回主要元素呢?很明显当n=2的时候,如果A[0]!=A[1],这个时候A是没有主要元素的。因为如果使用分治的话,子问题一定要有一个解得,所以当出现两个子问题的主要元素不一致的时候,如何来得到原问题的解呢?这时只能通过遍历,统计两个子问题对应的主要元素在更大的局部中出现的次数来解决。如果左边的主要元素在原问题的数组中出现的次数大于右边的主要元素那么答案就是左边的主要元素,否则的话就是右边的元素(需要注意的是返回右边的时候是包含右边的主要元素次数等于左边的情况,不过无所谓,因为后面的上一层还是要遍历统计的)。总结一下:

Divide 将输入数组A划分为左边A[0, n/2] 与右边A[n/2+1, n-1]两个数组

Conquer 左边的主要元素与右边的主要元素分别再各自递归的调用函数求解。

Merge 如果左边与右边的主要元素相等,那么就直接返回这个主要元素。如果不等那就统计这两个主要元素在A中的出现次数,然后返回较大的那个,次数相等的话左右两个主要元素随便返回其中一个。

复杂度

根据上面的思路可以写出递推式:首先是考虑最好的情况:就是每次都有左右两个子数组的主要元素相同,不需要判别,此时有递推公式:

每次分解后规模变为左右两个子树,因此下降到

,而每次比较左右两个子树最大深度与更新最大路径长度所需的时间为常数C。设当第k次的时候下降到规模为1的叶子节点,因此有
推出
所以有
,所以时间复杂度为O(n)。

考虑最坏的情况:每次都需要重新遍历来确定主要元素,也就是递归树中的每一层都需要遍历数组也就是O(n)的成本。所以有递推公式

根据主定理可以得出算法的最坏时间复杂度为

空间复杂度因为可以使用左右的索引来进行划分,不需要额外的空间所以是O(1)。

代码

#include<iostream>
#include<vector>
#include<map>
#include <stdio.h>using namespace std;
class Solution {private:int dc_majority(std::vector<int>&vec, int lo, int hi){if(lo>=hi) return vec[lo];int mid = lo + (hi-lo)/2;int l_ans = dc_majority(vec, lo, mid);int r_ans = dc_majority(vec, mid+1, hi);if(l_ans==r_ans) return l_ans;int l_ans_nums=0, r_ans_nums = 0;for(int i=lo; i<=hi; i++){if(vec[i]==l_ans) l_ans_nums++;if(vec[i]==r_ans) r_ans_nums++;}return l_ans_nums>r_ans_nums ? l_ans : r_ans;}
public:int majorityElement(vector<int>& nums) {int major=dc_majority(nums, 0, nums.size()-1);return major;}
};int main(int argc, char const *argv[])
{// Solution sol;// std::vector<int> vec={3,2,3};// int ans = sol.majorityElement(vec);// cout<<ans<<endl;// cin>>ans;ios::sync_with_stdio(false);int len;Solution Sol;int ans;while(cin>>len){vector<int> vec(len);for(int i = 0; i < len; i++) {cin>>vec[i];}ans = Sol.majorityElement(vec);cout<<ans<<endl;}return 0;
}

摩尔投票

每次从数组中删除一对不同的元素,按照题意到最后一定会剩下至少一个元素(假设每次不同的元素都是由一个主要元素和非主要元素组成的,这样的话最终仍然剩下主要元素,假设每次不同的元素都是非主要元素构成,最后肯定也会剩下多余的主要元素。也可以理解成捉对厮杀,因为主要元素的占比超过一半,其他非主要元素小于一半,所以最后一相减一定有主要元素剩下。)

代码

直接用的花花大神的:

class Solution {public:int majorityElement(vector<int>& nums) {int majority = nums.front();int count = 0;for (const int num : nums) {if (num == majority) ++count;else if (--count == 0) {count = 1;majority = num;}}return majority;}
};

复杂度

根据代码分析很容易得出时间复杂度为O(n), 空间复杂度为O(1)。

OJ的输入

这道题最开始是在UOJ上面的课程作业,我最开始做的时候不管怎么调,用什么方法,包括摩尔投票都会爆内存超过限制,后面分析出来的原因是:

int main(){Solution Sol;vector<int> vec;int n ;while(cin>>n){//int tmp = n;int element;while(n--){cin>>element;vec.push_back(element);}cout<<Sol.majorityElement(vec)<<endl;}}

我的输入是用push_back()来输入进vector中的,而vector的内存是动态申请的,不足的话会申请原来的两倍,所以造成了内存超过限制的原因,比如只需要11m的,假设上一次的vector申请到的是10m,所以下次就申请了20m造成了内存超过限制。

参考

个人博客原文,排版体验更佳。

http://zxi.mytechroad.com/blog/divide-and-conquer/leetcode-169-majority-element/

ios 替换数组中元素_leetcode169 数组中的主要元素相关推荐

  1. 【C 语言】数组 ( 数组相关地址 | 数组首元素地址 | 数组地址 )

    文章目录 一.数组相关地址 1.数组首元素地址 2.数组地址 二.代码示例 一.数组相关地址 数组首元素地址 与 数组地址 值相等 ; int array[10]; 其中 array + 1 的值是 ...

  2. java set中元素是数组_将HashSet中的元素转换为Java中的数组

    首先,创建一个HashSet及其元素-HashSet hs = new HashSet(); //将元素添加到哈希集 hs.add("B"); hs.add("A&quo ...

  3. dataframe数组做元素_数组 array 矩阵 list 数据框 dataframe

    #R语言备忘录三# #数组array和矩阵matrix.列表list.数据框dataframe #数组 #数组的重要属性就是dim,维数 #得到4*5的矩阵 z dim(z) z #构建数组 x #三 ...

  4. 数组(初识、创建数组、数组的元素、数组的变量)

    数组 数组:数据可以存放在变量里,每一个变量有一个名字,有一个类型,还有它的生存空间.如果我们需要保存一些相同类型.相似含义.相同生存空间的数据,我们可以用数组来保存这些数据,而不是用很多个独立的变量 ...

  5. python统计列表中元素个数_python中计算一个列表中连续相同的元素个数方法

    python中计算一个列表中连续相同的元素个数方法 最简单的例子: a = [1,1,1,1,2,2,2,3,3,1,1,1,3] # 问:计算a中最多有几个连续的1 很明显,答案是4 如果用代码实现 ...

  6. java一维数组插入元素_Java 数组 之 一维数组 追加 元素

    /** 数组分类 1. 一维数组 1.1 一维数组的定义和初始化 1.2 对一维数组的操作, 遍历,添加,插入,修改,删除,排序,查找 2. 二维数组 2.1 二维数组的定义和初始化 2.2 二维数组 ...

  7. php 查找数组相同元素,查找数组中重复的元素

    本文收集整理关于查找数组中重复的元素的相关议题,使用内容导航快速到达. 内容导航: Q1:在c语言中输入数组两个数组,查找重复元素并输出怎么写啊 可以一次读入N个数据.可以考虑以回车结束读入的一组. ...

  8. JS将数组中元素放到数组首位

    如下 var arrs= {}: var arrIndex: for (var i = 0; i < arrs.length; i++) { //比如对这个对象的default_focus字段做 ...

  9. 【DaVinci Developer专题】-24-IDT高阶应用:结构体中元素(数组,结构体,联合体)类型相互嵌套

    共15页 目录 1 创建一个Value IDT 2 创建一个Array IDT 3 创建一个Record IDT 4 创建一个Union IDT 5 创建一个Record IDT <

最新文章

  1. MapTask的工作机制
  2. golang 程序后台运行的方法 linux windows
  3. P3932 浮游大陆的68号岛
  4. 堆内存破坏检测实战--附完整调试过程
  5. 定时运行python脚本并发送邮件_python实现定时发送邮件到指定邮箱
  6. [js] fetch和axios请求的原理都是基于XMLHttpRerequst吗?
  7. android微信h5转原生支付,微信原生支付流程以及踩坑
  8. HDU1875prim算法求最小生成树
  9. 运动目标跟踪(十六)--OAB,SemiT,BSBT跟踪
  10. java 类 date_第十九回:Java常用类之Date
  11. 垂直滤波和水平滤波的区别_无锡有源滤波器的功能是_灿勤科技
  12. C UDR 的内存分配
  13. 企鹅龙(DRBL)无盘启动+再生龙(clonezilla)网络备份与还原系统
  14. 【BP靶场portswigger-服务端4】操作系统命令注入-5个实验(全)
  15. 初学SNMP,在spring boot 下使用snmp4j 做本地测试调通的记录
  16. Rust模板引擎Tera中文英文对照官方文档
  17. 字体靠右代码_html靠右文字代码
  18. 林语堂 - 人生的乐趣
  19. Linux glib库hash表GHashTable介绍
  20. 药品计算机管理系统法律法规,计算机系统管理制度

热门文章

  1. 抓取网页代码php,PHP抓取网页代码示例
  2. IE和Windows系统中的彩蛋
  3. AI迎来重要发展契机,开发者的机会在哪里?
  4. 一行代码没写,凭啥被尊为“第一位程序员”?
  5. 滴滴定制网约车D1即将登陆长沙 市民12月中可叫到
  6. 你熟知的开源项目,幕后推手竟然是他们?
  7. 微软智能语音多情感技术升级,晓晓中文语音突破14种风格
  8. 中国数据库产业的“高地战事”
  9. 干货 | 带你解析计算机视觉热门技术—目标检测与追踪
  10. 手把手带你深入解析静态分派 动态分派原理 | 原力计划