分治算法也是一种重要的求解问题的思路,移用百科的定义,分治就是分而治之,就是将一个规模比较大的问题分解为几个规模较小的问题,这些规模较小的问题是相互独立的,但是它们与原问题性质相同,可以用相同的思路进行继续分解求解,最后将这些小规模的问题求解出的解合并起来作为原问题的解,故而分治算法的求解过程为:
a、分解:寻找将原问题分解为求解几个规模比较小的问题,这些小问题和原问题的性值是相同的
b、求解:将问题规模分解到一定程度,可以用简单的方法进行求解
c、合并:将这些子问题的解合并起来作为原问题的解返回给调用者
因为子问题和原问题是同构的,所以分治在一定程度上可以借助递归算法进行实现,递归算法更像是一种模板。以下是可以用分治算法思想的案例:
1、归并排序
归并排序是将问题先分解,然后进行排序,最后将小规模的排好序的子解合并为一个原问题的解,详见https://www.cnblogs.com/codeMedita/p/7412568.html
2、求解最大值
给定一个无序的数组arr,求解arr中的最大值,可有两种计算:
a 直接遍历求解
def maxVal(arr):
int max=0;
for val in arr:
max=max>val?max:val;
return max
b 分治方法求解
def dividAndConquer(arr,leftIndex,rightIndex):
if(rightIndex==leftIndex+1 || rightIndex==leftIndex){
return Math.max(arr[leftIndex],arr[rightIndex]);
}
int mid=(leftIndex+rightIndex)/2;
int leftMax=dividAndConquer(arr,leftIndex,mid);
int rightMax=dividAndConquer(arr,mid,rightIndex);
return Math.max(leftMax,rightMax);
3、二分查找,给定一个从小到大有序的数组和一个值,求解改值在数组中的位置
def binarySearch(arr,leftIndex,rightIndex,val):
if(leftIndex>rightIndex) return false;
if(leftIndex==rightIndex):
return arr[leftIndex]==val;
int mid=(leftIndex+rightIndex)/2;
if(arr[mid]==val) return true;
if(arr[mid]>val){
if(leftIndex==mid) return false;
return binarySearch(arr,leftIndex,mid-1,val);
}
return binarySearch(arr,mid+1,right,val);
4、输出一条线上距离最近的两个点之间的距离值,给定一个数组arr,其值是从小到大有序的,输出最近点的距离
def minDistance(arr,left,right):
//同一个点返回极大值
if(arr[left]==arr[right]) return Integer.MAX
//相邻点的距离
if(right==left+1) return arr[right]-arr[left];
int mid=(left+right)/2;
//中间点的临近点的距离,这里很重要!!!
int midLeft=arr[mid]-arr[mid-1];
int midRight=arr[mid+1]-arr[mid];
//记录mid 附近两边的最小距离
midLeft=midLeft>midRight?midRight:midLeft;
int minLeft=minDistance(arr,left,mid);
int minRight=minDistance(arr,mid+1,right);
//记录mid 左侧和右侧的最小距离
minLeft=minLeft>minRight?minRight:minLeft;
//返回最小值
return midLeft>minLeft?minLeft:midLeft;
5、输出平面上距离最近的两个点的距离,给定一个点集,求出这个点集中最近两点的距离,这里需要进行一些排序操作,计算描述:
a 按横坐标递增的形式对点集进行排序,相同的横坐标的点击再用纵坐标从小大大进行排序,然后切分点集,切分方法mid=(left+right)/2
b 计算(left,mid)中的点集最小距离minleft,计算(mid,right)中的点集最小距离minright,此时mid-left<=3,right-mid<=3,如果
mid-left>3,则继续对(left,mid)中的点集进行切分,(mid,right)同理
c 计算mid+min(midleft,minright)之间的点击,按照遍历的方式进行计算
伪代码描述:
def minDis(point,left,right):
if(left+1==right):
//distance为预先定义好的计算方法
return distance(point[left],point[right]);
if(left+2==right):
dis1=distance(point[left],point[left+1]);
dis2=distance(point[left+1],point[right]);
dis3=distance(point[left],point[right]);
return min(dis1,min(dis2,dis3));
mid=(left+right)/2;
minleft=minDis(point,left,mid);
minright=minDis(point,mid+1,right);
//计算出mid点左右两侧中距离较短的点对距离
minMid=min(minleft,minright);
//以minMid为长度找出距离mid不超过minMid的点
for i=left to right:
if(Math.abs(point[mid].x-point[i])<d && mid!=i):
tempMemory.add(point[i]);
for i=0 to tempMemory.length:
for j=i+1 to tempMomory.length:
minMid=min(minMid,distance(point[i],point[j]);
return minMid;
java代码示例:
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 30 31 32 33 34 35 36 37 38 39 | //这里未进行开方<br><br> static int distance(List<Node> nodes,int left,int right){ Node leftNode=nodes.get(left),rightNode=nodes.get(right); int dis=(leftNode.x-rightNode.x)*(leftNode.x-rightNode.x)+ (leftNode.y-rightNode.y)*(leftNode.y-rightNode.y); return dis; } static int minDistance(List<Node> nodes, int left, int right){ if (right==left){ return Integer.MAX_VALUE; } if (right- 1 ==left){ return distance(nodes,left,right); } if (right- 2 ==left){ int m1=distance(nodes,left,left+ 1 ); int m2=distance(nodes,left+ 1 ,right); int m3=distance(nodes,left,right); return Math.min(m1,Math.min(m2,m3)); } int mid=(left+right)>> 1 ; int leftmid=minDistance(nodes,left,mid); int rightmid=minDistance(nodes,mid+ 1 ,right); int minMid=Math.min(leftmid,rightmid); List<Node> temp= new ArrayList<>(); for ( int i=left;i<right;i++){ if (Math.abs(nodes.get(i).x-nodes.get(mid).x)<minMid){ temp.add(nodes.get(i)); } } int dis= 0 ; for ( int i= 0 ;i<temp.size();i++){ for ( int j=i+ 1 ;j<temp.size();j++){ dis=distance(nodes,i,j); minMid=minMid>dis?dis:minMid; } } return minMid; } |
分治算法重要步骤:
1、分解:大的问题进行互不相干的小问题
2、解决:将小到一定规模的问题用简单的方法计算出结果
3、合并:将小问题的解进行整合作为原始问题的解返给调用方
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?