算法第二周 分治算法应用

算法题目 : Kth Largest Element in an Array

算法题目描述: 

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.

For example,
Given [3,2,1,5,6,4] and k = 2, return 5.

Note:
You may assume k is always valid, 1 ≤ k ≤ array's length.

算法分析:

这道题很好理解,就是求一个数组中的第k大的数字,首先想到的当然就是排序了,直接用sort()函数就可以排序,然后在返回第K大的数。然而考虑到算法的效率,这样肯定不行,需要用到其他排序算法。我们一般用到的排序算法有插入排序,快速排序,选择排序,归并排序等,各有各的优势。这里面和分治算法相关的就只有快速排序和归并排序了。

下面我们主要探讨归并排序和快速排序。对于归并排序,归并过程为:比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将第二个有序表中的元素a[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。

时间复杂度为  O( n log n)  空间复杂度为  O(n) 对于快速排序算法来说,它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
一趟快速排序的算法是:
1)设置两个变量i、j, 排序开始的时候:i=0,j=N-1;
2)以第一个数组元素作为关键数据,赋值给 key,即 key=A[0];
3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于 key的值A[j],将A[j]和A[i]互换;
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于 key的A[i],将A[i]和A[j]互换;
5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于 key,4中A[i]不大于 key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。
时间复杂度为  O( n log n)  空间复杂度为  O(log n)

通过对比我们可以很清楚的看到两者的时间复杂性是一样的,但是实际上用起来还是快速排序更胜一筹。这其中的主要原因还是要自己做实验来分析的,一般的解释是当数据量越来越大时,尽管归并排序的比较次数较少,但是归并排序后期的合并操作所花费的时间便越来越大,合并操作对整体的效率影响越来越明显,包括后面大量数据的赋值操作等。所以当数据量变大时,不需要专门合并的快速排序的优势就变得越发明显。归并排序比快速排序有优势的一点估计就是稳定性了。所以在权衡下,最终选取了快速排序。快速排序肯定都不陌生,就直接上代码吧!


算法代码(C++):

class Solution {
public:


    void quicksort(vector<int>& nums, int left, int right)
     {
         if(left < right)
         {
             int pivot = nums[left];
             int low = left;
             int high = right;
             
             while(low < high)
             {
                 while(low < high && nums[high] >= pivot)
                 high--;
                 
                 nums[low] = nums[high];
                 
                 while(low < high && nums[low] <= pivot)
                 low++;
                 
                 nums[high] = nums[low];
             }
             
             nums[low] = pivot;
             quicksort(nums, left, low - 1);
             quicksort(nums, low + 1, right);
             
         }
     }
     
      int findKthLargest(vector<int>& nums, int k) {
          quicksort(nums, 0, nums.size() - 1);
          return nums[nums.size() - k];
      }

 
};      


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值