本节需要先理解递归的含义:如何通俗易懂地理解递归
一、引例
描述
对给定数组中的数字进行排序,要求在O(nlogn)时间内完成
样例
输入:7
1 5 3 2 4 7 6
输出:
1 2 3 4 5 6 7
二、原理
定义(引自维基百科)
在计算机科学中,分治法是建基于多项分支递归的一种很重要的算法范型。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。
分析
思路一(归并):对于数组排序的问题,可以考虑将数组进行拆分,当数组被拆分到只剩一个数字的时候,那就不需要排序,直接输出即可,当数组中有2个数字的时候,只需要考虑2个数字的先后问题。拆分的过程很容易想到用递归解决,因为拆分就是整体和部分的思想,数组长度为 2 的数组,拆分只需要拆成第 0 项和第 1 项,以中间为基准,向两边拆分,而长度为 n 的数组,可以拆分成 2 项,每一项的长度都为 n/2,这两部分又可以继续拆分,直到数组被拆分成若干个大小为 2 的数组,那么只要用递归模拟出这个过程即可。 因此剩下要解决的是如何将若干个小部分合并起来的问题。
接下来考虑稍微复杂一点的情况,现有2个数字对,A:1 5 和 B:4 7,要将这两个数字对合并,需要设置两个指针i,j分别指向两个数字对的开头,然后开始扫描,A[i] < b[j] ,i++,然后 A[i] > B[j],j++,继续 A[i] < B[j],此时 i 不能再加,因此直接把 B 剩余的部分放在后面,就成功将 A 和 B 合并成同一个数组了。
将以上过程总结一下就是:
- 将一个数组从中间位置开始切分,利用递归完成这一过程,切分后的两部分开头的下标分别是 0 和 (n-1 - 0)/2,注意后半部分,再找到它的中间位置,为 [n-1 +(n-1 - 0)/2]/2,因此在函数编写过程中,注意中间位置是相对于切分后数组的中间位置。
- 找到递归基,需要知道什么时候不需要再切分,显然当进行到开头下标 >= 结尾下标时候,就不需要再切分。
- 递