问题是:给你一个数组,求解出现次数第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. [No00001D]解决5个问题,马上开口说英语

  2. java 26 - 6 网络编程之 TCP协议 传输思路 以及 代码

    TCP传输 Socket和ServerSocket 建立客户端和服务器 建立连接后,通过Socket中的IO流进行数据的传输 关闭socket 同样,客户端与服务器是两个独立的应用程序 TCP协议发送 ...

  3. c# HttpClient禁止缓存

    using (var client = new HttpClient())             {                //方法1:                 CacheContr ...

  4. PAT 1019. 数字黑洞 (20)

    给定任一个各位数字不完全相同的4位正整数,如果我们先把4个数字按非递增排序,再按非递减排序,然后用第1个数字减第2个数字,将得到一个新的数字.一直重复这样做,我们很快会停在有"数字黑洞&qu ...

  5. FFT的物理意义

    来源:学步园 FFT(Fast Fourier Transform,快速傅立叶变换)是离散傅立叶变换的快速算法,也是我们在数字信号处理技术中经常会提到的一个概念.在大学的理工科课程中,在完成高等数学的 ...

  6. Linux 网络编程详解十

    select int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *tim ...

  7. 跟我学习Storm_Storm基本架构

    Storm集群类似于一个Hadoop集群. 然而你在Hadoop的运行“MapReduce job”,在Storm上你运行 “topologies”. “job”和“topologies”本身有很大的 ...

  8. JS运动从入门到兴奋1

    hello,我是沐晴,一个充满了才华,却靠了照骗走江湖的前端妹子.在这个充满PS的年代,这你们都信,哈哈,废话不多说,今天要分享的是关注JS运动的知识.楼主一直认为,不管学习什么,核心思想才是王道,掌 ...

  9. Ext.NET-基础篇

    概述 本文介绍Ext.NET的基本概念,安装配置.布局以及容器,最后介绍了DirectEvents.DirectMethod.Listener,并提供了示例代码. 示例代码下载地址>>&g ...

  10. 深入理解计算机系统(2.4)---C语言的有符号与无符号、二进制整数的扩展与截断

    开篇请各位猿友允许LZ啰嗦几句,最近一直在写计算机系统原理这系列文章,也已经下定决心要把这本书的内容写完.主要目的其实是为了巩固LZ的理解,另外也想把这些内容分享给猿友们,毕竟LZ觉得这些内容对程序猿 ...