第二章实践作业
找第k小的数的分治算法
一、算法描述
给定一个无序数组A和整数k,找出数组中第k小的元素。采用分治思想,核心是快速选择算法。
自然语言描述:
分解:从数组A中选择一个基准元素pivot。
划分:将数组重新排列,使得小于pivot的元素在左边,等于pivot的元素在中间,大于pivot的元素在右边。
解决:
设左边部分元素个数为left_count,等于pivot的元素个数为equal_count。
若k小于等于left_count,则第k小的数在左半部分,递归在左半部分找第k小。
若k大于left_count加equal_count,则第k小的数在右半部分,递归在右半部分找第k减left_count减equal_count小。
否则,第k小的数就是pivot。
合并:该问题不需要合并,找到答案后直接返回。
二、时间复杂度分析
最好时间复杂度:
最好情况是每次选到的pivot都恰好将数组分成两半,或至少稳定缩小问题规模。
递归式为T(n)等于T(n/2)加O(n)。
根据主定理,T(n)等于O(n)。
所以最好时间复杂度为O(n)。
直观理解:每次划分只需要线性时间,问题规模每次减半,总代价为n加n/2加n/4加...等于O(n)。
最坏时间复杂度:
最坏情况是每次选到的pivot都是当前区间的最小值或最大值。
递归式为T(n)等于T(n-1)加O(n)。
展开得T(n)等于O(n)加O(n-1)加...加O(1)等于O(n^2)。
所以最坏时间复杂度为O(n^2)。
平均时间复杂度:
若基准随机选择或数据随机排列,平均时间复杂度为O(n)。
三、对分治法的体会和思考
分治法的核心是分解、解决、合并。分治法将规模较大的问题分解成若干规模较小、结构相似的子问题,分别求解后合并结果。归并排序需要合并,快速排序和快速选择不需要额外合并。
划分的平衡性决定效率。快速选择算法中,划分平衡时复杂度为O(n),划分极不平衡时退化为O(n^2)。基准的选择非常关键,随机化选择基准可以避免最坏情况频繁发生。
分治法不一定都要合并。传统分治法通常包括合并步骤,但快速排序和快速选择更强调分的过程。是否需要合并取决于问题本身。
分治法与减治法的联系。找第k小的数体现了减治思想:每次只递归进入一个子区间,而不是同时处理多个子问题。减治法可以看作分治法的一种特殊形式。
分治法的工程价值。分治法在算法设计中非常常见,如归并排序、快速排序、二分查找、快速选择、Strassen矩阵乘法、最近点对问题、大整数乘法等。其价值在于把复杂问题结构化,利用递归和划分降低问题规模,获得较好的时间复杂度。
浙公网安备 33010602011771号