问题是:给你一个数组,求解出现次数第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. url编码base编码解码十六进制

    0x25346425353425343525333525343325366125343525373725346425353125366625373825346425343425363725346225 ...

  2. linux运维中的命令梳理(二)

    回想起来,从事linux运维工作已近5年之久了,日常工作中会用到很多常规命令,之前简单罗列了一些命令:http://www.cnblogs.com/kevingrace/p/5985486.html今 ...

  3. SPM12manual,统计部分(8-10)笔记

    fMRI model specifictaion GLM based 包括以下步骤:①明确GLM设计矩阵:②用经典或贝叶斯方法估计GLM参数:③利用对比向量检查结果,生成统计参数图(SPMs)以及后验 ...

  4. 使用Jquery向一个空白网页动态创建一个iframe,及嵌入页面,和向嵌入页面传参

    [csharp] view plaincopyprint?using Microsoft.VisualBasic; using System; using System.Collections; us ...

  5. js判断是否在微信浏览器中打开

    用JS来判断,无论是android 还是iphone,ipad 都可以 function is_weixn(){ var ua = navigator.userAgent.toLowerCase(); ...

  6. Html5 Egret游戏开发 成语大挑战(五)界面切换和数据处理

    经过前面的制作,使用Egret的Wing很快完成了开始界面和选关卡界面,下面通常来说就是游戏界面,但此时界面切换和关卡数据还没有准备好,这次讲解界面的切换和关卡数据的解析.前面多次修改了Main.ts ...

  7. CodeGenerator.cs

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace CiCe ...

  8. Android 开发之旅:view的几种布局方式及实践

    本文的主要内容就是分别介绍以上视图的七种布局显示方式效果及实现,大纲如下: 1.View布局概述 2.线性布局(Linear Layout) 2.1.Tips:android:layout_weigh ...

  9. 小图标外链API

    网页上有些分享的小图标,比如分享到facebook,weibo,qq空间等功能的时候,图标以前一般是自己做一个css sprite.当一个网站的图标变了的时候,比如facebook变成assbook的 ...

  10. 傻瓜看完都可以简单使用Git

    作为当下最流行的版本控制系统,Git是一个分布式版本控制系统,跟SVN等集中式版本控制有很多使用上的不同.万事开头难,想要最快学会使用Git,最简单的就是下了客户端就直接去用,一边用一边学.本文手把手 ...