问题是:给你一个数组,求解出现次数第K多的元素。当然leetcode上的要求是算法复杂度不能大于O(N*logN)。

首先这个问题我先是在leetcode上看到,当时想了两种做法,做到一半都觉得不是很好,正在思考别的方法。然后在牛客网上看别人的面试经历,看到一个应聘者和用我几乎完全一样的思路尝试在面试中解决这个问题(HashMap-->TreeSet),但是都没解决出来。这个问题确实是一个乍看不难但是要实际解决又会不停发现自己思路有问题的问题,于是我索性记录一下这两种想法和解决之道。

拿到这个问题的时候我第一时间想到了用HashMap解决,键值对的键是数组中的元素的值,值是目前出现的次数,当第一次出现的时候值给1,以后发现已经存在那么就取出值加1再放进去。这个方法的思想是用类似于上一篇博文中的方法来做。核心是用hash算法形成一个元素与储存位置的映射来实现查找操作的常量时间复杂度。这么做的结果是你能在O(N)的算法复杂度情况下得到一个HashMap,它储存了每一种元素和其出现的个数。这个时候一个很具体的问题就出现了,下一步本来需要对出现次数进行一个排序,然后取出出现次数第K大的那个元素。但是问题是键值对的映射方式是从键映射到值,也就是说你用HashMap可以找出值的集合,但是无法找出与这个值对于的键。比如你通过排序知道了最频繁的次数是5,但是你不知道到底谁出现了5次。这个地方其实我要解释一下,不是说你就完全做不到实现反映射,而是第一,HashMap实现的是映射你强行根据值寻找键不符合其设计初衷,第二,实现的过程比较复杂我想需要很大的算法复杂度完全抵消了使用HashMap带来的好处。比如一个键只能对应一个值,但是一个值可能有多个键对应。(每一个数组中的元素都有确定的出现次数,但是出现次数为K的元素可能不止一个)。要解决这些问题等等。真的解决了也就不是这道题目的问题了。

第二时间我想到了用TreeSet,因为它既可以根据你的重写的equal()方法判断是否等于和去重,又可以对你输入数据用comparator进行排序。我就想,我干脆写一个类,里面即方数字本身用于比较是否相等(hashcode和equal),又放当前出现的次数,又实现comparator接口来对当前出现的次数进行排序。我的期望是好的,但是在一开始的思考的时候我忽视了(确实没想到)一个根本的问题,这个问题直接导致我的这个想法完全不能按照我设想的实现。随着你遍历的进行,你的某个数的出现的次数可能从1变到2变到3。所以你有一个不停动态修改TreeSet的内容对象的过程。但是你无法获得TreeSet中值为当前数组值的那个对象的引用。比如说我现在遍历到数组中的5这个元素,于是我去TreeSet中找值为5的对象,但是找不到(没有提供相应的方法)。当然确实也不应该有这样的方法,你想你都知道值是5了,可是你又不知道具体引用的值,TreeSet也没办法帮你。如果用遍历强行去找会导致一个很复杂的过程,算法复杂度高(红黑树的遍历)。同时,TreeSet是按照某种规律排序的,大量的修改其值的操作(通过先删除再add,或者这个问题中的用add覆盖)会影响其效率因为要维护某种顺序。所以这个问题中也不推荐这么做。

虽然以上两种做法都么能直接解决这个问题,但是给我带来了思考。

最后还是做出来了,大致就是第一种方法不过键值对的值是我写的类,最后再用堆排序。这个做法还是挺蠢得我觉得。貌似最佳做法使用桶排序O(N)?以后再研究研究这个。

寻找数组中第K频繁的元素的更多相关文章

  1. [经典算法题]寻找数组中第K大的数的方法总结

    [经典算法题]寻找数组中第K大的数的方法总结 责任编辑:admin 日期:2012-11-26   字体:[大 中 小] 打印复制链接我要评论   今天看算法分析是,看到一个这样的问题,就是在一堆数据 ...

  2. 寻找数组中第K大数

    1.寻找数组中的第二大数 using System; using System.Collections.Generic; using System.Linq; using System.Text; u ...

  3. 寻找数组中第K大的数

    给定一个数组A,要求找到数组A中第K大的数字.对于这个问题,解决方案有不少,此处我只给出三种: 方法1: 对数组A进行排序,然后遍历一遍就可以找到第K大的数字.该方法的时间复杂度为O(N*logN) ...

  4. [leetcode]215. Kth Largest Element in an Array 数组中第k大的元素

    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...

  5. 215。数组中第K个最大元素(堆实现)

    class Solution: def findKthLargest(self, nums: List[int], k: int) -> int: """堆排序思想 ...

  6. 寻找数组中的第K大的元素,多种解法以及分析

    遇到了一个很简单而有意思的问题,可以看出不同的算法策略对这个问题求解的优化过程.问题:寻找数组中的第K大的元素. 最简单的想法是直接进行排序,算法复杂度是O(N*logN).这么做很明显比较低效率,因 ...

  7. C语言:将3*5矩阵中第k列的元素左移到第0列,第k列以后的每列元素依次左移,原来左边的各列依次绕到右边。-在m行m列的二维数组中存放如下规律的数据,

    //将3*5矩阵中第k列的元素左移到第0列,第k列以后的每列元素依次左移,原来左边的各列依次绕到右边. #include <stdio.h> #define M 3 #define N 5 ...

  8. 前端算法题:找出数组中第k大的数字出现多少次

    题目:给定一个一维数组,如[1,2,4,4,3,5],找出数组中第k大的数字出现多少次. 例如:第2大的数是4,出现2次,最后输出 4,2 function getNum(arr, k){ // 数组 ...

  9. 查找数组中第k大的数

    问题:  查找出一给定数组中第k大的数.例如[3,2,7,1,8,9,6,5,4],第1大的数是9,第2大的数是8-- 思考:1. 直接从大到小排序,排好序后,第k大的数就是arr[k-1]. 2. ...

随机推荐

  1. gnuplot 的安装

    需要同时安装gnuplot和gnuplot-x11才能画出图 sudo apt-get install gnuplot gnuplot-x11 gnuplot not showing the grap ...

  2. Android fragment之间消息传递

    1. 在Fragment里定义一个内部接口, 在Fragment初始化方法里, 把父Activity转换成这个接口, 赋值给成员变量 public class DummyFragment extend ...

  3. SQL SERVER 系统库查询

    本文内容主要来自网络,如有错误请路过的大牛指点迷津. 1.sqlserver 数据库最大并发连接数 sqlserver的最大连接数虽然说是不限制,但实际的限制数量是32767,如果需要超出这个数量,一 ...

  4. CSS3中的Rem值与Px之间的换算

    bootstrap默认 html{font-size: 10px;} rem是一个相对大小的值,它相对于根元素<html>, 比如假设,我们设置html的字体大小的值为html{font- ...

  5. 解决Cannot change version of project facet Dynamic web module to 2.5

    我们用Eclipse创建Maven结构的web项目的时候选择了Artifact Id为maven-artchetype-webapp,由于这个catalog比较老,用的servlet还是2.3的,而一 ...

  6. Apache下开启SSI配置使html支持include包含

    写页面的同学通常会遇到这样的烦恼,就是页面上的 html 标签越来越多的时候,寻找指定的部分就会很困难,那么能不能像 javascript 一样写在不同的文件中引入呢?答案是有的,apache 能做到 ...

  7. DOM 元素节点几何量与滚动几何量

    当在 Web 浏览器中查看 HTML 文档时,DOM 节点被解析,并被渲染成盒模型(如下图),有时我们需要知道一些信息,比如盒模型的大小,盒模型在浏览器中的位置等等,本文我们就来详细了解下元素节点的几 ...

  8. Euler Level 2

    闲下来的时候就做点,慢慢的也终于到达Level 2了.

  9. (404) 未找到 获取StatusCode状态码

    异常代码: (HttpWebResponse)req.GetResponse(); 当执行这段代码出现异常 解决问题 那如果我们想获得错误发生时候服务器段错误页面的源代码该如何做呢? 其实非常非常简单 ...

  10. python2.7到python3代码转换脚本2to3的一些介绍

       你的位置: Home ‣ Dive Into Python 3 ‣ 难度等级: ♦♦♦♦♦   使用2to3将代码移植到Python 3 ❝ Life is pleasant. Death is ...