时间复杂度

10道Hadoop面试真题及解题思路

一笑奈何 提交于 2019-11-29 09:26:31
搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。 (一)海量日志数据,提取出某日访问百度次数最多的那个IP。 首先是这一天,并且是访问百度的日志中的IP取出来,逐个写入到一个大文件中。注意到IP是32位的,最多有个2^32个IP。同样可以采用映射的方法, 比如模1000,把整个大文件映射为1000个小文件,再找出每个小文中出现频率最大的IP(可以采用hash_map进行频率统计,然后再找出频率最大 的几个)及相应的频率。然后再在这1000个最大的IP中,找出那个频率最大的IP,即为所求。 算法思想:分而治之+Hash IP地址最多有2^32=4G种取值情况,所以不能完全加载到内存中处理; 可以考虑采用“分而治之”的思想,按照IP地址的Hash(IP)%1024值,把海量IP日志分别存储到1024个小文件中。这样,每个小文件最多包含4MB个IP地址; 对于每一个小文件,可以构建一个IP为key,出现次数为value的Hash map,同时记录当前出现次数最多的那个IP地址; 可以得到1024个小文件中的出现次数最多的IP,再依据常规的排序算法得到总体上出现次数最多的IP; (二)搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。 假设目前有一千万个记录(这些查询串的重复度比较高

【排序算法】快速排序原理及Java实现

一世执手 提交于 2019-11-29 09:01:52
1、基本思想: 快速排序是我们之前学习的冒泡排序的升级,他们都属于交换类排序,都是采用不断的比较和移动来实现排序的。快速排序是一种非常高效的排序算法,它的实现,增大了记录的比较和移动的距离,将关键字较大的记录从前面直接移动到后面,关键字较小的记录从后面直接移动到前面,从而减少了总的比较次数和移动次数。同时采用“分而治之”的思想,把大的拆分为小的,小的拆分为更小的,其原理如下:对于给定的一组记录,选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分,直到序列中的所有记录均有序为止。 2、复杂度分析: (1)最坏时间复杂度 最坏情况是指每次区间划分的结果都是基准关键字的左边(或右边)序列为空,而另一边区间中的记录仅比排序前少了一项,即选择的关键字是待排序记录的最小值或最大值。最坏情况下快速排序的时间复杂度为 。 (2)最好时间复杂度 最好情况是指每次区间划分的结果都是基准关键字的左右两边长度相等或者相差为1,即选择的基准关键字为待排序的记录的中间值。此时进行比较次数总共为 nlogn ,所以最好情况下快速排序的时间复杂度为 。 (3)平均时间复杂度 快速排序的平均时间复杂度为 。在所有平均时间复杂度为 O(nlogn) 的算法中

十分钟弄懂:数据结构与算法之美 - 时间和空间复杂度

两盒软妹~` 提交于 2019-11-29 07:49:55
复杂度分析是整个算法学习的精髓,只要掌握了它,数据结构和算法的内容基本上就掌握了一半了。 1. 什么是复杂度分析 ? 数据结构和算法解决是 “如何让计算机更快时间、更省空间的解决问题”。 因此需从执行时间和占用空间两个维度来评估数据结构和算法的性能。 分别用时间复杂度和空间复杂度两个概念来描述性能问题,二者统称为复杂度。 复杂度描述的是算法执行时间(或占用空间)与数据规模的增长关系。 2. 为什么要进行复杂度分析 ? 和性能测试相比,复杂度分析有不依赖执行环境、成本低、效率高、易操作、指导性强的特点。 掌握复杂度分析,将能编写出性能更优的代码,有利于降低系统开发和维护成本。 3. 如何进行复杂度分析 ? 3.1 大 O 表示法 算法的执行时间与每行代码的执行次数成正比,用 T(n) = O(f(n)) 表示,其中 T(n) 表示算法执行总时间,f(n) 表示每行代码执行总次数,而 n 往往表示数据的规模。这就是大 O 时间复杂度表示法。 3.2 时间复杂度 1)定义 算法的时间复杂度,也就是算法的时间量度。 大 O 时间复杂度表示法 实际上并不具体表示代码真正的执行时间,而是表示 代码执行时间随数据规模增长的变化趋势 ,所以也叫 渐进时间复杂度 ,简称 时间复杂度 (asymptotic time complexity)。 例子1: function aFun() {

算法

一世执手 提交于 2019-11-29 07:01:21
1.算法 1.1时间复杂度 时间复杂度:用来评估算法运行效率的一个式子! 由于print()一次与print多次,执行时间相差很小,所以时间复杂度统一为O(1)。 相对于循环来说,中间执行的代码时间相对来说很小,所以只要是循环,时间复杂度只与循环的次数有关。 小节: 1.时间复杂度是用来估计算法运行时间的一个式子。 2.一般来说,时间复杂度高的算法比复杂度低的算法慢。 3.常见的时间复杂度效率 O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n2logn)<O(n3) 4.复杂的时间复杂度 O(n!) O(2n) O(nn) … 快速判断算法复杂度规模(适用于大多数情况): 1.没有循环,为O(1) 2.循环n次,为O(n) 3.k层循环,为n^k 4.循环减半,为log2^n 复杂情况,根据算法执行过程判断 1.2空间复杂度 空间复杂度:用来评估算法内存占用大小的式子。 1.算法只是使用了一些变量,空间复杂度为O(1)。 2.算法使用了长度为n的一维列表,空间复杂度为O(n)。 3.算法使用了m行n列的二维列表,空间复杂度为O(m*n) 在实际编程中,我们都会以空间来换取时间,即使占用内存,也要争取速度。 2.递归 2.1常见例子 2.2汉诺塔问题 要求把所有圆盘从A上挪到另一个柱子上 小圆盘不能放在大圆盘上 一次只能移动一个盘子 #!/usr/bin

Java集合时间复杂度

拈花ヽ惹草 提交于 2019-11-29 06:46:24
List ArrayList LinkedList Arraylist 可增长的数组长度 查询快 get() set() 常数级 插入和现有所有项的删除代价昂贵 除非在表的末端 ArrayList 是线性表(数组) get() 直接读取第几个下标,复杂度 O(1) add(E) 添加元素,直接在后面添加,复杂度O(1) add(index, E) 添加元素,在第几个元素后面插入,后面的元素需要向后移动,复杂度O(n) remove()删除元素,后面的元素需要逐个移动,复杂度O(n) 总结:查 O(1) 增 末尾0(1)中间0(n) 删0(n) 移动是消耗时间复杂度的 LinkedList 双链表 删快 新项的插入和现有项的删除都是非常的快 在表的前端添加和删除都是常数级 addFrist removeFrist addLast removeLast getFirst getLast 但是不容易做索引 LinkedList 是链表的操作 get() 获取第几个元素,依次遍历,复杂度O(n) add(E) 添加到末尾,复杂度O(1) add(index, E) 添加第几个元素后,需要先查找到第几个元素,直接指针指向操作,复杂度O(n) remove()删除元素,直接指针指向操作,复杂度O(1) 总结:查 O(n) 增 末尾O(1)中间O(n) 删O(1) Set集合有三个常见的实现类

两数之和(leetCode)

蓝咒 提交于 2019-11-29 06:43:41
首先两层for循环的是时间复杂度是 On^2, 在此就不说了. 所以我们这边要优化时间复杂度. 此时间复杂度为 n. /** * 两值之和 * @param nums 数组 * @param target 两值之和 * @return */ public int[] twoSum(int[] nums, int target) { // 存入数据 key 为值 , value 为数组下标 Map<Integer, Integer> map = new HashMap<>(); for(int i = 0; i < nums.length ; i++){ int p = target - nums[i] ; // 校验是否已存在和其相加之和为target 的数据在map 中 if (map.containsKey(p)) { return new int[]{map.get(p),i}; } map.put(nums[i],i); } return null; } 来源: https://blog.csdn.net/bfy0914/article/details/100544207

(14)Go查找表求回旋镖数量

孤街浪徒 提交于 2019-11-29 06:38:34
1)暴力解法:时间复杂度O(n^3) 2)查找表 通过题目可以看出每一个点 i 都是一个枢纽,对于每个点 i,遍历其余点到 i 的距离,存储到查找表 时间复杂度O(n^2) 空间复杂度为O((n-1)+(n-2)+...+1) = O(n) 实现 // 时间复杂度O(n^2) // 空间复杂度最大为O((n-1)+(n-2)+...+1) = O(n) func numberOfBoomerangs(points [][]int) int { count := 0 for i1, v1 := range points { // m[key]val: key为值,val为出现的次数 m := make(map[int]int) for i2, v2 := range points { if i1 != i2 { m[distance(v1, v2)]++ } } // val>1,则有 val * (val - 1) 个三元组 for _, v := range m { if v > 1 { count += v * (v - 1) } } } return count } // 计算两点距离的平方 func distance(a, b []int) int { return (a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1]) }

(16)Go滑动窗口求存在重复元素

回眸只為那壹抹淺笑 提交于 2019-11-29 06:36:55
思路:如果t==0,则变成219题目,解决方法 参考:(15)Go查找表配合滑动窗口求存在重复元素----https://www.jianshu.com/p/78c421a40023 滑动窗口方法:处理t==0和t>0的情况,如果t==0下面的方法时间复杂度是O(2n)=O(n) 维持1个长度为<=k的滑动窗口,若窗口内有不同元素的绝对值<=t,返回true 时间复杂度O(n^2) func containsNearbyAlmostDuplicate(nums []int, k int, t int) bool { if k == 0 { return false } startI := 0 endI := 1 for startI < len(nums)-1 { // startI != endI不能省略,因为k=1时,两者可能相等,出现自己跟自己比较的情况 if startI != endI && abs(nums[endI]-nums[startI]) <= t { return true } // 维持长度为k的[startI...endI]区间 if endI-startI == k || len(nums)-1 == endI { startI++ // 如果t==0,时间复杂度是O(2n)=O(n) // 如果t!=0,每次startI+1

20王道——数据结构——绪论

落花浮王杯 提交于 2019-11-29 06:32:58
1.1数据结构的基本概念 1.可以用(抽象数据类型)定义一个完整的数据结构 2.以下数据结构中,(树)是非线性数据结构 3.以下属于逻辑结构的是(有序表) 4.以下与数据的存储结构无关的是(栈) 5.以下关于数据结构的说法正确的是(数据的逻辑结构独立于其存储结构) 6.在存储数据时,通常不仅要存储各数据元素的值,而且要存储(数据元素之间的关系) 7.链式存储设计时,结点内的存储单元地址(一定连续)。 1.2算法和算法评价 1.一个算法应该是(问题求解步骤的描述) 2.若某算法的时间复杂度为O(n^2),表明该算法(执行时间与n^2成正比) 3.以下算法的时间复杂度为(O(log2(n))) void func(int n){ int i=1; while(i<=n) i=i*2; } 求算法时间复杂度步骤: 基本语句是……,共执行了……次,故T(n)=O(……)。 来源: https://blog.csdn.net/yqajsj/article/details/100539648

LeetCode 136. 只出现一次的数字 C++

旧巷老猫 提交于 2019-11-29 06:08:31
给定一个 非空 整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 说明: 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗? 示例 1: 输入: [2,2,1] 输出: 1 示例 2: 输入: [4,1,2,1,2] 输出: 4 法一: 第一时间想到的方法,使用map记录数组中每个值出现的次数,first为值,second为出现次数。时间复杂度O(n*logn)(在map中寻找键为key的迭代器的时间复杂度为logn),空间复杂度O(n) class Solution { public: int singleNumber(vector<int>& nums) { map<int,int> mp; for(int i = 0 ; i<nums.size();i++) { int temp = nums[i]; map<int,int>::iterator it = mp.find(temp); if(it == mp.end()) mp[temp] = 1; else mp[temp] += 1; } for(map<int,int>::iterator it = mp.begin();it != mp.end();it++) { if(it->second == 1) return it->first; } } }; 法二: