"分而治之"(Divide and Conquer)是一种算法设计策略,它将一个问题分解成更小的、相互独立的子问题,然后递归地解决这些子问题,最后将它们的解合并起来,得到原始问题的解。这个策略通常包含三个步骤:
-
分解(Divide): 将原问题分解为若干个规模较小的子问题。这一步通常通过递归的方式来实现。
-
解决(Conquer): 递归地解决这些子问题。如果子问题足够小,就直接解决。
-
合并(Combine): 将子问题的解合并成原问题的解。
这个思想常常用于解决一些复杂的问题,例如排序、查找、图算法等。一些著名的算法,比如归并排序和快速排序,就是分而治之的典型例子。
下面以归并排序为例来说明分而治之思想的应用:
归并排序的步骤
-
分解: 将待排序的数组分成两半。
-
解决: 递归地对这两半数组进行归并排序。
-
合并: 将两个已排序的子数组合并成一个有序的数组。
这个过程一直递归下去,直到子问题的规模足够小,可以直接解决。通过这样的分治策略,最终整个数组被排序。
分而治之的优点
-
简化复杂问题: 将一个大问题分解为若干个小问题,使问题的解决变得更加简单和直观。
-
提高效率: 在某些情况下,分而治之可以通过并行处理来提高算法的效率。
-
可复用性: 将问题分解为独立的子问题,这些子问题可以在不同的上下文中被复用。
-
可维护性: 代码结构清晰,易于理解和维护。
总体来说,分而治之是一种强大的问题解决思想,能够在设计算法时提供清晰的思路和结构。
二分法查找实例
#include <stdio.h>
//1.正常数组的查找
int searchData(int array[], int arrayNum, int posData)
{
for (int i = 0; i < arrayNum; i++)
{
if (array[i] == posData)
return i;
}
return -1;
}
//2.正常的二分查找--->有序的
int binarySerachData(int array[], int arrayNum, int posData)
{
int left = 0;
int right = arrayNum - 1; //右边的数组下标是等于数组长度-1
while (left <= right)
{
int mid = (left + right) / 2;
if (array[mid] == posData)
{
return mid;
}
else if (array[mid] > posData)
{
right = mid - 1;
}
else
{
left = mid + 1;
}
}
return -1;
}
//3.分而治之的二分查找
int binarySearch(int array[], int left, int right, int posData)
{
if (left > right)
return -1;
int mid = (left + right) / 2;
if (array[mid] == posData)
return mid;
else if (array[mid] > posData) //左边的问题
{
return binarySearch(array, left, mid - 1, posData);
}
else
{
//右边问题
return binarySearch(array, mid+1, right, posData);
}
}
int main()
{
int array[10] = { 0,1,2,3,4,5,6,7,8,9 };
printf("index:%d\n", binarySerachData(array, 10, 1));
printf("index:%d\n", binarySearch(array, 0,9, 1));
return 0;
}
双重找最值实例
#include <stdio.h>
/*
1.找最大值和最小值
*/
//正常写法
void searchMaxMin(int array[], int arrayNum, int* maxIndex, int* minIndex)
{
int max = array[0];
int min = array[0];
*maxIndex = 0;
*minIndex = 0;
for (int i = 1; i < arrayNum; i++)
{
if (array[i] > max)
{
max = array[i];
*maxIndex = i;
}
if (array[i] < min)
{
min = array[i];
*minIndex = i;
}
}
}
void searchMaxMin2(int array[], int arrayNum, int* maxIndex, int* minIndex)
{
//1.只有一个元素
if (arrayNum == 1)
{
*maxIndex = *minIndex = 0;
}
//2.先解决奇偶问题
int n = 1;
if (arrayNum % 2 == 1)
{
*maxIndex = *minIndex = 0;
}
else
{
if (array[0] > array[1])
{
*maxIndex = 0;
*minIndex = 1;
}
else
{
*maxIndex = 1;
*minIndex = 0;
}
n = 2;
}
for (int i = n; i < arrayNum; i += 2)
{
if (array[i] > array[i + 1]) //下一组找出最小和最大的
{
if (array[i] > array[*maxIndex]) //大的跟大的比
{
*maxIndex = i;
}
if (array[i + 1] < array[*minIndex]) //小的跟小的比
{
*minIndex = i + 1;
}
}
else
{
if (array[i + 1] > array[*maxIndex])
{
*maxIndex = i + 1;
}
if (array[i] < array[*minIndex])
{
*minIndex = i;
}
}
}
}
int main()
{
int array[10] = { 4,5,7,8,9,0,1,6,2,3 };
int maxIndex = -1;
int minIndex = -1;
searchMaxMin(array, 10, &maxIndex, &minIndex);
printf("max=%d\nmin=%d\n", maxIndex, minIndex);
maxIndex = -1;
minIndex = -1;
searchMaxMin2(array, 10, &maxIndex, &minIndex);
printf("max=%d\nmin=%d\n", maxIndex, minIndex);
return 0;
}