壹 ❀ 引

做题做题,再忙每天都要抽空做一道题!今天来做一道有趣的题,题目来自多数元素,题目描述如下:

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:

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

示例 2:

输入: [2,2,1,1,1,2,2]
输出: 2

我们来简单的分析下题目,看看有几种做法实现它。

贰 ❀ 题解分析

在做题之前,我们先来简单科普一个数学名词众数,所谓众数其实就是在一堆数据中出现最多次的数。当然,特殊情况下一个数组会有众数也是合理的,一般用M表示众数。

[1,1,1,2,3]//众数为1
[1,1,2,2,3]//众数为1,2
[1,2,3,4]//没有峰值,无众数

而题目要求是找出现次数大于n/2的数,其实说到底,就是也算一种特殊的众数,而且这个众数一定只有一个。为啥这么说呢,因为出现次数都已经大于所有数个数的一半了(M>n/2),剩下的数怎么都不可能比这个众数更多,或者与之一样多,比如:

[1,1,1,2,3]//1为众数,2与3已经没机会与1平起平坐,或者超越1了
[1,1,2,2,3]//没有一个数超过n/2,所以没有

所以对于这道题来说,一定只有只有一个数是最多的,我们只需要找到这个出现次数最多的数即可,怎么做呢?

贰 ❀ 壹 桶排序

我一开始想的就是桶排序,找出数组中最大的数,然后建立(max+1)个桶,为啥要加1,因为数组索引是从0开始的,如果最大的数是3,new Array(3)之后,最大的索引其实是2,那么数字3找不到对应的桶,说干就干:

/**
* @param {number[]} nums
* @return {number}
*/
var majorityElement = function (nums) {
// 找出最大数
let max = Math.max(...nums);
let backet = new Array(max + 1).fill(0);
nums.forEach(item => {
// 将对应桶的数递增
backet[item]++;
});
// 找到数字最大的那个桶,也就是我们想要的数了
return backet.findIndex(item => item > nums.length / 2);
};

这个实现在本地跑是可以的,但是提交了就报错,错误理由leetcode也给不出来,反正我也挺莫名其妙的。

贰 ❀ 贰 字典

这个实现显然是不太优化的,打个比方,假设不凑巧的是[9999,9999,1],那我们就得建立9999个桶,也就是说数字范围给的越大,咱们最后遍历桶耗时也就越久,有没有更棒的做法呢?其实我们可以使用哈希表或者字典直接来统计每个数字出现的次数,这里我用字典来做:

/**
* @param {number[]} nums
* @return {number}
*/
var majorityElement = function (nums) {
// 建立一个字典
let dic = {};
nums.forEach(item => {
// 将数字作为key,出现次数作为value,每出现一次自增1
dic[item] = dic[item] || 0;
dic[item]++;
});
// 找到value最大的key返回即可
return Object.keys(dic).find(item => {
return dic[item] > nums.length / 2;
});
};

贰 ❀ 叁 排序

还有没有更直接的办法呢?其实这里就需要动下脑筋了。我们在前面说,本题是找出出现次数比n/2还要多的数,且这个数只有一个。如果我们将数组进行排序,会发生什么呢?

我们简单脑补一下,假设数组n为偶数,比如一共4个,那么这个众数起码得有3个;假设是奇数,比如5个,那么这个数也起码得有3个,看个图:

不管奇数偶数,取中间一位的数就是我们要找的数,有同学就说了,不对啊,偶数除不断,那就取中间数,不能整除就向下取整:

/**
* @param {number[]} nums
* @return {number}
*/
var majorityElement = function (nums) {
nums.sort((a, b) => a - b);
return nums[Math.floor(nums.length/2)];
};

有同学就要问了,为啥不能向上取整,看图片上取整好像也可以,这是因为我们还得考虑只有一个元素的情况,比如[1]1/2=0.5,1次比0.5要大,所以也满足,如果用ceil那就取到undefined了。

贰 ❀ 肆 摩尔投票法

首先,什么是摩尔投票法呢?这里引用知乎用户的解释,原答案地址

啥意思?由于我们已知数组中一定有这个最多的数,且数量超过数组长度一般,我们把每个数比喻成一个国家,数字出现频率表示这个国家有多少人,现在发动战争,以一个人消耗一个人来看,最后剩下的人一定是最多国家的人。

有同学可能就想要数字出现顺序的问题,虽然你多,但是如果大家都打你,都消耗你怎么办?没关系,前面已经说了,这个国家人数超过了总人数一半,就算你们一起联合起来消耗我,我还是能有剩下的人,那么这个剩下的人就是最多的数了。

有同学又要问了,那假设一开始这个数,不是最多的那个那个,直接被消耗完了咋办?没关系,我们可以假定第一个数表示最多,然后开始内耗,只要内耗变成了0,我们就将下一位数认定为最多,继续开始内耗,运气不好,就是最多的数和所有的其它数打架。运气好就是其它数内耗的差不多了,最多的数能剩下不止一个。所以不管怎么说,我们总是能找到最多的那个数:

/**
* @param {number[]} nums
* @return {number}
*/
var majorityElement = function (nums) {
// 假设第一个数是最多的数
let num = nums[0],
// 默认参战人数是1
count = 1;
for (let i = 1; i < nums.length; i++) {
// 开始打仗,相同是自己人,加1
if (num == nums[i])
count++;
else {
// 反之内耗掉,判断变成0没有,变了就取下一位成为假定最多的那个
count--;
if (count == 0) {
num = nums[i + 1];
};
};
};
return num;
};

那么到这里,本文结束。

JS leetcode 多数元素 题解分析的更多相关文章

  1. js实现页面元素随着内容的滚动而滚动

      CreateTime--2017年9月4日16:55:06 Author:Marydon js实现页面元素随着内容的滚动而滚动 分析: CSS样式,使用绝对定位确定好页面元素在屏幕的位置(如:正中 ...

  2. js获取隐藏元素宽高的方法

    网上有一些js获取隐藏元素宽高的方法,但是可能会存在某些情况获取不了. 例如: <!DOCTYPE html> <html lang="en"> <h ...

  3. js改变HTML元素的值

    js改变HTML元素的值(常用,备忘) <!DOCTYPE html> <html> <body> <h1>我的第一段 JavaScript</h ...

  4. JS控制HTML元素的显示和隐藏

    JS控制HTML元素的显示和隐藏 利用来JS控制页面控件显示和隐藏有两种方法,两种方法分别利用HTML的style中的两个属性,两种方法的不同之处在于控件隐藏后是否还在页面上占空位. 方法一: 1 2 ...

  5. 【转】第6篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:自动注册JS脚本+自动反射方法分析

    作者: 牛A与牛C之间 时间: 2013-11-21 分类: 技术文章 | 暂无评论 | 编辑文章 主页 » 技术文章 » 第6篇:Xilium CefGlue 关于 CLR Object 与 JS ...

  6. 【转】第5篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:自动注册JS脚本+委托回调方法分析

    作者: 牛A与牛C之间 时间: 2013-11-19 分类: 技术文章 | 暂无评论 | 编辑文章 主页 » 技术文章 » 第5篇:Xilium CefGlue 关于 CLR Object 与 JS ...

  7. <八>面向对象分析之UML核心元素之分析类

    一:基本概念        ---->在那大数项目中,分析类是被忽视的一种非常有用的元素.        ---->分析类用于获取系统中主要的“职责簇”,他们代表系统的原型类,是系统必须处 ...

  8. JS1 js获取dom元素方法

     js获取dom元素方法  1.通过ID选取元素(getElementById) 1)使用方法:document.getElementById("domId")         其 ...

  9. 使用JS控制伪元素的几种方法

    一. 缘由: 本文源于在OSC社区中,有人提问如何用jq获取伪元素.我第一想法是强大的CSS Query应该可以获取伪元素吧. 然而事实上,CSS Query并不能.即我们不能通过$(":b ...

  10. arcgis api for js之echarts开源js库实现地图统计图分析

    前面写过一篇关于arcgis api for js实现地图统计图的,具体见:http://www.cnblogs.com/giserhome/p/6727593.html 那是基于dojo组件来实现图 ...

随机推荐

  1. gradle简介与windows安装操作

    本文为博主原创,转载请注明出处: 目录 1.Gradle 简介 2.gradel 与 maven 对比 3.安装 gradle 3.1.安装jdk 3.2.下载gradle 3.3.下载解压到指定目录 ...

  2. @Import 源码解析

    转发请注明出处: @Import通过快速导入的方式实现把实例加入spring的IOC容器中:一般@EnableXXX注解是通过@Import实现具体的功能(@EnableXXX注解上加个@Import ...

  3. 一文搞清楚Java中的方法、常量、变量、参数

    写在开头 在上一篇文章:一文搞清楚Java中的包.类.接口 中我们讲了Java中的包.类和接口,今天继续将剩下的方法.常量.变量以及参数梳理完. Java中的变量与常量 在JVM的运转中,承载的是数据 ...

  4. 【TouchGFX】实测工程所在路径深度不可超过10级(10级有效)

    实测环境 win10 64bit touchgfx designer 4.13.0

  5. JMS微服务架构 - 关于事务提交失败,自动重新提交的机制

    用JMS编写的微服务,由调用端决定了各个微服务执行时,是否需要保持事务的一致性. 也就是RemoteClient在调用微服务方法前,先调用BeginTransaction明确后面所调用的微服务需要保持 ...

  6. linux 内存盘的使用方式与验证

    linux 内存盘的使用方式与验证 背景 某些情况下, 硬盘的写入是一个很大的瓶颈 使用 内存文件系统的方式应该能够极大的提高IO的速度. 内存盘的优点是比较快, 缺点就是数据不是持久化的. 其实还是 ...

  7. [转帖]线上一个隐匿 Bug 的复盘

    前言 之前负责的一个项目上线好久了,最近突然爆出一 Bug,最后评估影响范围将 Bug 升级成了故障,只因为影响的数据量有 10000 条左右,对业务方造成了一定的影响. 但因为不涉及到资金损失,Bu ...

  8. [转帖]兆芯官方的CPU测试成绩,我复现不了

      https://baijiahao.baidu.com/s?id=1734998483605483848 下图是兆芯网官上的公开测试成绩,测试对象是3.0GHz的KX-U6880A. 有几个问题: ...

  9. SQLSERVER 通过分离附加的方式迁移文件存储的位置.

    有时候 SQLSERVER的数据库所在磁盘满了,或者是性能变的很差, 需要转换一下磁盘的位置. 这个时候最简单的办法是通过分离附加的方式进行处理. 0. 准备工作 0.1 备份-备份-备份 没有备份 ...

  10. CCPC Finals 2021 H Harie Programming Contest (网络流&支配树的妙用)

    Link 题意: 给一个二分图,求有多少种方案删去恰好两个点,使得最大匹配数不变.\(n,m\le 2\times 10^5\). 二话不说先跑一遍 Dinic 网络流,设残量网络形成的图为 \(G\ ...