🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇
⭐分治⭐
🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇🎇
前言
分治算法(Divide and Conquer),顾名思义,将一个大问题分成多个小问题,然后分别解决这些小问题,最后将它们的解合并起来得到整体的解。这个算法的核心思想是将问题分割成更小的、相同结构的子问题,然后将子问题的解合并成原问题的解。
分治算法的运行流程通常包括三个步骤:分解、解决和合并。
分解:将原问题分解成若干个规模较小的子问题。这个步骤通常通过递归实现,直到子问题足够简单可以直接求解。
解决:递归地求解子问题。这可以通过相同的方法再次应用分治算法,继续将子问题分解成更小的子问题,直到达到基本情况可以直接求解。
合并:将子问题的解合并成原问题的解。当所有子问题都解决之后,将它们的解合并起来,得到原问题的解。
分治算法通常适用于满足两个条件的问题:
- 可以将原问题分解成相同结构的子问题。
- 子问题的解可以通过合并得到原问题的解。
分治算法在计算机科学中应用广泛,例如在排序算法中具有重要地位。著名的排序算法,如归并排序和快速排序,都是基于分治算法的思想。
归并排序通过分治的方式将一个无序数组分割成更小的子数组,然后递归地对子数组进行排序,最后将排好序的子数组合并成一个有序的数组。
快速排序也是通过分治的方式将一个无序数组分割成两个子数组,然后递归地对子数组进行排序,最后合并得到完整的有序数组。
总而言之,分治算法是一种非常有用的算法设计技巧,能够有效地解决一些复杂问题。它将问题分解成较小的子问题,通过递归解决子问题,并最终将它们的解合并成整体解,从而实现高效的问题求解。
2. 最⼩的k个数(medium)
题目链接:LCR 159. 库存管理 III - 力扣(LeetCode)
算法思路:(快速选择算法)
在快排中,当我们把数组「分成三块」之后: [l, left] [left + 1, right - 1] [right, r] ,我们可以通过计算每⼀个区间内元素的「个数」,进⽽推断出最⼩的k个数在哪 些区间⾥⾯。 那么我们可以直接去「相应的区间」继续划分数组即可。
这道题其实有很多做法,
1. 直接排序 O(n * logN)
2.堆实现 O(n * logK)
3.分治 O(N) 这里只实现第三种做法,如果另外两种有需求的话可以在评论区评论.
代码实现:
package Divide_and_Conquer;
import java.util.Arrays;
import java.util.Random;
public class Solution5 {
public static void main(String[] args) {
System.out.println(Arrays.toString(inventoryManagement(new int[]{0, 0, 1, 2, 4, 2, 2, 3, 1, 4}, 8)));
}
public static int[] inventoryManagement(int[] stock, int cnt) {
int[] arr = new int[cnt];
if(stock.length==0||cnt==0){
return arr;
}
//这里其实有很多种做法,本题只用分治的方式来解答这道题
//这道题和上道第k大的数很相似,那个只用找一个数,这个是找连续的几个数
//但实际上做法是一样的 找最小的k个数
//把数组分三块,去基准元素里找对应个数的数
find(stock,0,stock.length-1,cnt);
for(int i =0;i<cnt;i++){
arr[i] = stock[i];
}
return arr;
}
public static void swap(int[] nums,int i ,int j ){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
public static void find(int[] nums,int l,int r,int k){
//先找基准元素
int key = nums[new Random().nextInt(r-l+1)+l];
//数组分三块
int left = l-1,right = r+1,i = l;
while(i<right) {
if (nums[i] < key) {
swap(nums, ++left, i++);
} else if (nums[i] == key) {
i++;
} else {
swap(nums, --right, i);
}
}
//看个数来找
int c = r-right+1,b=right-left-1,a=left-l+1;
if(a>k){
// 在左边里面排一下再找
find(nums,l,left,k);
} else if(a+b>=k){
return;
}else{
find(nums,right,r,k-a-b);
}
}
}
总结
以上是总结的第4道分治的题,后续会更新一系列的分治算法相关的题哦。
关于分治算法中使用快速排序变形的题目就到这里了,后继续更新 归并排序对分治算法的应用。
点个赞👍,会让作者开心很久的,感谢阅览。