分治算法
例题
大整数乘法
大整数:超过计算机能直接表示和处理的整数
设 和 为大整数,均为 n 未。
可二进制拆分为两部分,前 0 ~ n/2 位为 A,n/2 + 1 ~ n 位为 B。 同理拆为 C 和 D 两部分。
故:
需要进行 4 次 位乘法 ; ; ; ,以及 2 次移位( 可用移位达成)、3 次加法操作。
得到时间复杂度的计算公式:
时间复杂度计算:
与使用竖式乘法的时间复杂度一样,但是 可以进行变形减少乘法次数,将 $ (AD+BC) $ 变形为 ,乍一看乘法从原来的 2 次变为了 3 次,但是 ; 在其他项中也有出现,所以实际上是将 2 次乘法变成了 1 次乘法,整条式子变成了 3 次乘法,故:
计算后得到:
时间复杂度得到改进。
快速排序
递归加分治的经典排序算法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| int Partition(vector<int> &arr, int start_index, int end_index) { int left_index = start_index, right_index = end_index + 1; while(true) { while (arr[++left_index] < arr[start_index] && left_index <= end_index); while (arr[--right_index] > arr[start_index]); if (right_index <= left_index) break; swap(arr[left_index], arr[right_index]); }
swap(arr[right_index], arr[start_index]);
return right_index; }
void QuickSort (vector<int> &arr, int start_index, int end_index) { if (start_index < end_index) { int p = Partition(arr, start_index, end_index); QuickSort(arr, start_index, p-1); QuickSort(arr, p + 1, end_index); } }
|
随机基准划分:期望获得较为对称的划分。
Partition
函数不变,在外包裹一层函数,用于将随机基准与队首元素互换。QuickSort
函数调用该外层函数进行划分即可。
1 2 3 4 5
| int RandomPartition(vector<int> &arr, int start_index, int end_index) { int rand_index= rand() % (end_index - start_index + 1) + start_index; swap(arr[start_index], arr[rand_index]); return Partition(arr, start_index, end_index); }
|
随机选择算法(选择最 k 小的元素)
在快速排序的 Partition
函数的基础上,划分后的数组基准之右的元素均大于基准之左的元素,若左边的元素数量小于 k,则代表目标数一定在右边的元素中,反之则在左边的元素中,并以此选择一边继续划分,直至左边的长度为 k - 1 为止。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| int RandomSelect(vector<int> &arr, int start_index, int end_index, int k) { int partition_index = RandomPartition(arr, start_index, end_index); int left_length = partition_index - start_index; if (left_length == k - 1) return arr[partition_index]; if (left_length >= k) { return RandomSelect(arr, start_index, partition_index, k); } else { return RandomSelect(arr, partition_index + 1, end_index, k - left_length + 1); } }
|