一个小算法有哪些问题

每日一个小算法有哪些之两数之囷

给定一个整数数组 nums 和一个目标值 target请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标

你可以假设每种输入只会对應一个答案。但是你不能重复利用这个数组中同样的元素。

这个题目是不是很简单啊

首先,我们想到的第一种方案就是for循环嵌套循環。如下:

再速度上是不是快了很多

欢迎大家留下更好的算法有哪些。一起学习一起成长

例如:进入12。34,56。78此8数芓,最小的4图的12,34。

思路1:最easy想到的方法:先对这个序列从小到大排序然后输出前面的最小的k个数就可以。假设选择高速排序法来進行排序则时间复杂度:O(n*logn)

注:针对不同问题我们应该给出不同的思路。假设在应用中这个问题的规模不大或者求解前k个元素的频率非常高,或者k是不固定的

那么我们花费较多的时间对问题排序。在以后是使用中能够线性时间找到问题的解整体来说,那么思路一嘚解法是最优的

思路2:在思路1的基础上更进一步想想,题目并没有要求要查找的k个数甚至后n-k个数是有序的。既然如此咱们又何必对铨部的n个数都进行排序列?如此。我们能想打的一个方法是:遍历n个数先把最先遍历到得k个数存入大小为k的数组之中,对这k个数利用选擇或交换排序,找到k个数中的最大数kmax(kmax设为k个元素的数组中最大元素)用时O(k)(你应该知道,插入或选择排序查找操作须要O(k)的时間)后再继续遍历后n-k个数,x与kmax比較:假设x<kmax则x取代kmax,并再次又一次找出k个元素的数组中最大元素kmax‘;假设x>kmax则不更新数组。这样每次哽新或不更新数组的所用的时间为O(k)或O(0),整趟下来总的时间复杂度平均下来为:n*O(k)=O(n*k)

思路3:与思路2方法类似,仅仅是用容量為k的最大堆代替思路2中数组的作用(从数组中找最大数须要O(k)次查找而从更新一个堆使之成为最大堆仅仅须要O(logk)次操作)。详细做法例如以丅:用容量为k的最大堆存储最先遍历到的k个数并如果它们即是最小的k个数。建堆费时O(k)后有k1<k2<…<kmax(kmax设为大顶堆中最大元素)。继续遍曆数列每次遍历一个元素x。与堆顶元素比較x<kmax,更新堆(用时logk)否则不更新堆。

思路4:按编程之美中给出的描写叙述类似高速排序嘚划分方法,N个数存储在数组S中再从数组中随机选取一个数X(随机选取枢纽元。可做到线性期望时间O(N)的复杂度)把数组划分为Sa和Sb倆部分,Sa<=X<=Sb假设要查找的k个元素小于Sa的元素个数,则返回Sa中较小的k个元素否则返回Sa中全部元素+Sb中小的k-|Sa|个元素。像上述过程一样这个运鼡类似高速排序的partition的高速选择SELECT算法有哪些寻找最小的k个元素,在最坏情况下亦能做到O(N)的复杂度

oh。太酷了有没有!

思路5:仍然用到數据结构:堆。详细做法为:针对整个数组序列建最小堆建堆所用时间为O(n),然后取堆中的前k个数总的时间复杂度即为:O(n+k*logn)。

思蕗6:与上述思路5类似不同的是在对元素数组原地建最小堆O(n)后,然后提取K次可是每次提取时。换到顶部的元素仅仅须要下移顶多k次就足夠了下移次数逐次降低(而上述思路5每次提取都须要logn,所以提取k次思路5须要k*logn。而本思路仅仅须要K^2)此种方法的复杂度为O(n+k^2)。

此方法可能不太直观一个更直观的理解是:每次取出堆顶元素后,最小堆的性质被破坏了我们须要调整最小堆使之满足最小堆的性质。

因为我們仅仅须要求取前k个数我们无需将整个堆都完整的调整好。仅仅需保证堆的最上面k个数是最小的就能够即第一趟调整保持第0层到第k层昰最小堆,第二趟调整保持第0层到第k-1层是最小堆…依次类推。

几个简单的提取前k个元素居然能够有这么多的思路来实现,复杂度逐渐減少感觉是多么酷的一件事情啊。

以下给出思路三和思路四的參考代码(这些代码都凝结了高速排序和堆排序的思想所以说之前的算法有哪些有用,主要是思想):

if (arr[i] < arr[0])//就是这一个地方跟堆排序不一样这里仅仅是交换比堆顶大的元素。 // 避免特殊数据下的算法有哪些退化吔可 // 以通过对整个数据进行洗牌预处理 // 将p增加较小的组。能够避免分组失败也使分组 // 更均匀,提高效率 为了简单起见这里仅仅是单纯嘚选取第一个元素作为枢纽元素。这样选取枢纽就难避免使得算法有哪些easy退化。
//从右向左查找直到找到第一个小于枢纽元素为止 //从左姠右查找,直到找到第一个大于枢纽元素为止 }else//前low个数值已经是前k个数值后k-low个在后半部分中

以下是《算法有哪些设计与分析》书中给出的┅种思路,源代码例如以下:

//取三数中值作为枢纽元能够非常大程度上避免最坏情况 }这个高速选择SELECT算法有哪些。类似高速排序的划分方法N个数存储在数组S中,再从数组中选取“中位数的中位数”作为枢纽元X把数组划分为Sa和Sb俩部分,Sa<=X<=Sb假设要查找的k个元素小于Sa的元素个數,则返回Sa中较小的k个元素否则返回Sa中全部元素+Sb中小的k-|Sa|个元素。这样的解法在平均情况下能做到  O(N)  的复杂度
以下是算法有哪些导论Φ给出的一种方法:

《算法有哪些导论》介绍了一个随机选取主元的选择算法有哪些RANDOMIZED-SELECT。它每次都是随机选取数列中的一个元素作为主元茬  O(n) 的时间内找到第k小的元素,然后遍历输出前面的k个小的元素平均时间复杂度:  O(n+k)=O(n)  (当k比較小时)。

我们知道高速排序是鉯固定的第一个或最后一个元素作为主元,每次递归划分都是不均等的最后的平均时间复杂度为:  O(n*logn) 。而RANDOMIZED-SELECT与普通的高速排序不同它烸次递归都是随机选择序列,从第一个到最后一个元素中任一一个作为主元

x ← A[r] //以最后一个元素作为主元 k ← q - p + 1 //k表示子数组 A[p…q]内的元素个数,處于划分低区的元素个数加上一个主元元素 //得到的k 大于要查找的i 的大小则递归到低区间A[p。q-1]中去查找 //得到的k 小于要查找的i 的大小则递归箌高区间A[q+1,r]中去查找

2. 取出每一组的中位数,随意排序方法比方插入排序。

3. 递归的调用selection算法有哪些查找上一步中全部中位数的中位数設为x,偶数个中位数的情况下设定为选取中间小的一个

4. 用x来切割数组。设小于等于x的个数为k大于x的个数即为n-k。

5. 若i==k返回x。若i<k在小于x嘚元素中递归查找第i小的元素。若i>k在大于x的元素中递归查找第i-k小的元素。

终止条件:n=1时返回的即是i小元素。

版权声明:本文博客原创攵章博客,未经同意不得转载。

我要回帖

更多关于 算法问题 的文章

 

随机推荐