前言

点击查看算法介绍

五大算法

  • 分治算法
  • 动态规划
  • 贪心算法
  • 回溯算法
  • 分支限界算法

WX搜素"Java长征记"对这些算法也有详细介绍。

分治算法

一、算法概述

    简单来说,分治算法就是“分而治之”,即就是讲一个规模很大很复杂的问题分
成若干份相同或相似的更小的子问题,直到最后可以简单的直接求解,将所有子问题
的解合并即得到原问题的解。

二、分治策略的基本思想

  • 将原始问题划分或者归结为规模较小的子问题
  • 递归或迭代求解每个子问题 将子问题的解综合得到原问题的解

注意:

  • 子问题与原问题的性质必须一致
  • 子问题必须可以独立求解
  • 递归停止时,子问题必须能直接求解

三、时间复杂性分析

在分治算法中,假设原问题总规模为n,我们假设分解和合并所用时间为C(n)和D(n),假设W(x)为处理一个规模为x的问题所用的时间。每一个子问题是原问题规模的1/a。

如果原问题规模<=最小子问题的规模,既可以直接求解,那么其时间复杂度是一个常数。否则,W(n)=aW(n/a)+C(n)+D(n);

四、分治思维

简单来说就是由小到大,先理清最小子问题如何去解决,然后逐渐增加问题规模,找到递归或者迭代方法,编写程序。

五、经典例子

  • 二分归并排序
  • 汉诺(Hanoi)塔
  • 快速排序
  • 二分检索
  • 查找第k大元素

如果想获得以下这些景点例子的文本形式的代码,WX搜索"Java长征记",回复"算法代码"即可。

●二分归并排序

设计思想:

1、将规模为n的原问题划分为规模为n/2的子问题;
2、继续划分,划分至规模为n/4的,继续一直到规模为1,可以直接求解,这块分治就结束了;
3、从规模1到n/2依次陆续归并排好序的子数组,直到原始数组。

伪码:

算法 Merge Sort (A, p, r)
输入:数组 A[ p … r]
输出:元素按从小到大排序的数组 A

  1. if p < r
  2. then q <-( p + r)/2 对半划分子问题
  3. Merge Sort (A, p, q) 子问题1
  4. Merge Sort (A, q+1, r) 子问题2
  5. Merge (A, p, q, r) 综合解

程序:

//归并排序public static void mergeSort(int[] nums,int begin,int end){/* int length=nums.length;if(length<=1){return;}if(end<=begin){return;}*/int length=end-begin+1;if(length<=1){return;}/*分*/int mid=(begin+end)/2;mergeSort(nums, begin, mid);mergeSort(nums, mid+1, end);/*治*/merge(nums, begin,mid, end);}public static void merge(int[] nums,int begin,int mid,int end){if(mid>=end){return;}int length=end-begin+1;int[] temp=new int[length];int k=0;int i=begin;int j=mid+1;while(i<=mid&&j<=end){if(nums[i]<nums[j]){temp[k]=nums[i];i++;}else{temp[k]=nums[j];j++;}k++;}/*传进来前半部分已经排完*/if(i>mid){while(j<=end){temp[k]=nums[j];j++;k++;}}/*后半部分已排完*/if(j>end){while(i<=mid){temp[k]=nums[i];i++;k++;}}/*重新存进原数组*/for(int m=0;m<length;m++){nums[begin+m]=temp[m];}}

图解:


合并排序部分细节图解

时间复杂度分析:

假设原问题规模为n,二分归并排序最坏情况: W(n)=2W(n/2)+n-1 其中子问题最小规模为1,W(1)=1;

W(n)=nlogn - n + 1
时间复杂度为O(nlogn)

●汉诺(Hanoi)塔

游戏介绍

在汉诺塔游戏中,有三个塔座:A、B、C。几个大小各不相同,从小到大一次编号的圆盘,每个原盘中间有一个小孔。最初,所有的圆盘都在A塔座上,其中最大的圆盘在最下面,然后是第二大,以此类推.

该游戏的目的是将所有的圆盘从A塔移到B塔;C塔用来放置临时圆盘,游戏的规则如下:

  • 一次只能移动一个圆盘
  • 任何时候都不能将一个较大的圆盘压在较小的圆盘上面.
  • 除了第二条限制,任何塔座的最上面的圆盘都可以移动到其他塔座上.

设计思想

游戏分析:

假设共有n个盘子 当n=1,盘子记为1,直接将1从A移到C塔即可;

当n=2,盘子从小到大记为1,2,先将1从A移到B,再将2移到C,最后将1移到C塔即可;

当n=3,盘子从小到大记为1,2,3,此刻只需将1,2看为一个盘子即可,记为1+2,先将1+2移至B塔,2在下1在上,然后将3移到C塔,最后将1+2盘移到C塔;

当1+2盘移到C塔时,由于每次只能动一个盘子,所以可以看做一个新的只有两个盘的Hanoi游戏。 …

当n=n,盘子从小到大依次记为1,2,3…n-1,n,此刻将1到n-1看为一个盘,移到到C塔,再将n移到C,最后将1到n-1看为一个新的Hanoi游戏移到C塔,依次类推到只有1个盘子(盘子1)。

设计思想:

  • 将原问题归结为规模为 n-1 的2个子问题.
  • 继续归约,将原问题归结为规模为n-2 的 4 个子问题. 继续…,当子问题规模为1时,归约过程截止
  • 从规模 1到 n-1,陆续组合两个子问题的解. 直到规模为n.

伪码

算法 Hanoi (A, C, n) // n个盘子A到C

  1. if n=1 then move (A, C) //1个盘子A到C
  2. else Hanoi (A, B, n-1)
  3. move (A, C)
  4. Hanoi (B, C, n-1) 设 n个盘子的移动次数为 T(n)
    T(n) = 2 T(n-1) + 1,
    T(1) = 1, T
    (n)=2n-1

程序:

//hanoi塔public static void solve(int n) {    hanoi(n, "A", "B", "C");  // 已知条件n个圆盘和A、B、C三个塔}/*** 若要让第n个圆盘成功从A塔移动到C塔,需要让前n-1个圆盘先从A塔移动到B塔,然后让第n个圆盘从A塔移动到C塔,* 最后让第n-1个圆盘从B塔移动到C塔,至于如何将前n-1个圆盘从A塔移动到B塔或者从A塔移动到C塔,仅仅是和父问题相同的子问题* 采用父问题的解决方案即可。*/private static void hanoi(int n, String a, String b, String c) {if (n == 1) {// 只有一个圆盘时直接从A塔移到C塔move(n, a, c);} else {         hanoi(n - 1, a, c, b);// 将前n-1个圆盘从A塔移到B塔       move(n, a, c);   // 将第n个圆盘从A塔移到C塔            hanoi(n - 1, b, a, c);//看为一个新的hanoi塔游戏, 将前n-1个圆盘从B塔移到C塔,A塔为中间塔}} private static void move(int n, String i, String j) {System.out.println("第" + n + "个圆盘," + "从" + i + "塔移动到" + j+"塔");}

时间复杂度分析

hanoi塔游戏的递推公式为T(n)=2T(n-1)+1,时间复杂度为O(2^n)

●快速排序

设计思想

找一个基准数,将比其小的放置左边大的放置右边,然后再将基准数前后部分按照此方法继续分开,直至只有1个数时停止分裂,将所有的子序列合起来即排序完成

伪码:

算法:quicksort(Arr,p,r) 输入:数组Arr[p…r] 输出:元素按从小到大排序的数组 Arr
1.if p < r then q<- partition(Arr,p,r)
quicksort(Arr,p,q-1)
quicksort(Arr,p+1,r) }
2.else return 其中partition(Arr,p,r)就是分治部分。

部分图解

例,快速排序的一次递归运行

程序:

//快速排序
public static void quickSort(int[] num, int begin, int end){if(begin<end){int reference = num[begin];//将区间的收元素作为基准数int index=begin;//记录初始参考数下标int i=begin;//从左开始寻找比基准数小的元素int j=end;//从右开始寻找比基准数大的元素while(i<j){while(i<j && num[j]>=reference)j--;while(i<j && num[i]<=reference)i++;swap(num,i,j);//交换i,j}swap(num,i,index);//将参考数放置中间(分界线处左小右大)quickSort(num,begin,i-1);quickSort(num,i+1,end);}elsereturn ;}public static void swap(int num[],int i,int j) {int temp;temp=num[i];num[i]=num[j];num[j]=temp;}

时间复杂度分析

快速排序的时间复杂度为O(n2)

●二分检索

设计思想

  • 通过 x 与中位数的比较,将原问题归结为规模减半的子问题,如果 x 小于中位数,则子问题由小于 x 的数构成,否则子问题由大于 x的数构成.
  • 对子问题进行二分检索
  • 当子问题规模为 1 时,直接比较 x与 T[m],若相等则返回 m,否则返回 -1.

伪码:

算法 Binary Search (T, l, r, x) 输入:数组 T,下标从 l 到 r,查找数 x 输出:j // 若x在T 中,
j 为下标; 否则为 -1

  1. l<-1; r<-n
  2. while l<=r do
  3. m<-(l +r)/2 // m为中间位置
  4. if T[m]=x then return m // x是中位数
  5. else if T[m]>x then r<-m-1
  6. else l<-m+1
  7. return -1

程序:

//二分检索
public static int BinarySearch(int num[],int begin,int end,int x) {if(x>num[end]||x<num[begin]||begin>end||num==null)return -1;int mid=(begin+end)/2;if(num[mid]==x)return mid;else if(num[mid]>x)return BinarySearch(num,begin,mid-1,x);else if(num[mid]<x)return BinarySearch(num,mid+1,end,x);elsereturn -1;}

【针对于有序序列,所以在二分检索前要对数组中元素进行排序,可直接调用Arrays.sorrt(a);进行排序】

时间复杂度分析:

W(n) = W ( n/2 ) +1,W(1) = 1
解出W(n)= log n + 1,算法时间复杂度为O(log n)。

●查找第k大元素

设计思想

随机确定一个数组下标,将对应的元素作为参考数,然后将比该数大的元素放在其左边并且记录其左区间元素数量(count从1开始计数),小于等于的置于其右,若k小于参考数前面的元素数量,则第k大的数在左区间,否则在右区间(在右区间寻找第k-count大的数),然后再继续归约,直到k==count

伪码:

find(A,left,right,k)

输入:数组 A,下标从 left 到 right,第几大k

输出:数组A中对应的第k大的数
1.partition(A,left,right)
2.if k<count
then find(A,left,middle-1,k)
3.else if k>count
then find(A,middle+1,end,k-count)
4.else return A[midlle] partition为分区,计数部分。

程序:

//找第k大的数public static int find(int a[],int left,int right,int k){int temp;int index = (int)Math.random()*a.length;    //随机选取一个下标的元素作为定值来进行比较//swap(a[left],a[index]);temp=a[left];a[left]=a[index];a[index]=temp;int middle = left;int count = 1;                     //记录比选定元素大的元素的个数int i;for(i = left+1;i<=right;i++)     //计算所选定的元素左边的元素的个数{if(a[i]>a[left])                //将大的元素排在所选定点得左边{//swap(a[middle],a[i]);temp=a[middle];a[middle]=a[i];a[i]=temp;count++;middle++;}}/*分治*/if(k<count){                     //如果需要找的第k个大的元素小于左边的元素数量,那么第k个大的元素在左边这个区间,再递归调用去找return  find(a,left,middle-1,k);}else if(k>count){            //如果大于左边元素数量,则在右边区间找return  find(a,middle+1,right,k-count);}elsereturn a[middle];   //如果k==count说明要找的元素刚好是middle}

时间复杂度分析

时间复杂度为O(n);

干货分享

想了解更多的算法、数据结构以及关于Java基础知识的,WX搜索"Java长征记"

程序员都会的五大算法之一(分治算法),恶补恶补恶补!!!相关推荐

  1. 程序员都会的五大算法之四(回溯算法),恶补恶补恶补!!!

    前言 点击查看算法介绍 五大算法 分治算法 动态规划 贪心算法 回溯算法 分支限界算法 WX搜素"Java长征记"对这些算法也有详细介绍. 回溯算法 一.算法概述 回溯算法是一种择 ...

  2. 程序员都会的五大算法之三(贪心算法),恶补恶补恶补!!!

    前言 点击查看算法介绍 五大算法 分治算法 动态规划 贪心算法 回溯算法 分支限界算法 WX搜素"Java长征记"对这些算法也有详细介绍. 贪心算法 一.算法概述 贪心算法也叫贪婪 ...

  3. 程序员都会的五大算法之五(分支限界法),恶补恶补恶补!!!

    前言 点击查看算法介绍 五大算法 分治算法 动态规划 贪心算法 回溯算法 分支限界算法 WX搜素"Java长征记"对这些算法也有详细介绍. 分支限界算法 一.算法概述 分支限界法其 ...

  4. 程序员考核的五大死因

    程序员考核的五大死因(上) 程序员作为企业开发力量的最核心资产,无疑得到公司从上至下的一致关注.开发是个智力密集型产业,程序开发的特点是,付出相同时间的情况下,两个开发者之间的产能会相差十几甚至几十倍 ...

  5. Python程序员都会喜欢的6个库

    在编程时,小挫折可能与大难题一样令人痛苦.没人希望在费劲心思之后,只是做到弹出消息窗口或是快速写入数据库.因此,程序员都会喜欢那些能够快速处理这些问题,同时长远来看也很健壮的解决方案. 下面这6个Py ...

  6. 每个程序员都会的35种小技巧

    每个程序员都会的35个jQuery小技巧! 1. 禁止右键点击 $(document).ready(function(){     $(document).bind("contextmenu ...

  7. 分治法的关键特征_算法系列之常用算法之一----分治算法

    一.基本概念 在计算机科学中,分治法是一种很重要的算法.分治算法,字面上的解释是"分而治之",分治算法主要是三点: 1.将一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问 ...

  8. 2.Python算法之分治算法思想

    1.什么是分治算法? 2.为什么需要分治算法? 3.分治算法基础 4.分治算法的解题一般步骤 5. 用分治算法--求顺序表中的最大值 5. 用分治算法--判断某个元素是否在列表中 6. 用分治算法-- ...

  9. 贪心算法、分治算法和动态规划的区别

    贪心算法.分治算法和动态规划的区别 (1)分治法(divide and conquer method) 将原问题划分成若干个规模较小而结构与原问题相似的子问题,递归的解决这些子问题,然后再合其结果,就 ...

最新文章

  1. SSL 数字证书助力电子商务,让您网络购物更安心
  2. python画图代码星星-Python打印“菱形”星号代码方法
  3. 高等数学同济第七版课后答案下册
  4. python获取列表中指定元素的下标
  5. poj 2515 差分序列,排列组合
  6. linux不自动创建sda1,linux下头挂载新硬盘(转)
  7. 修改Linux系统日期与时间date clock
  8. 在android中使用USB进行通信的4种方法
  9. 深入浅出Nintex——更新PeopleandGroup类型的Field
  10. Okhttp之同步和异步请求简单分析
  11. python+selenium 使用for循环,遍历 定位 获取 单个元素中想要的值
  12. smc数显压力表设定方法_日本SMC数显压力表中文说明书ISE40A-01-P-ML
  13. 数学建模 Lingo 基本算法模板
  14. 计算的威力,智慧的传奇——Fabrice Bellard
  15. 莫队算法学习笔记(一)——普通莫队
  16. ABAQUS关联验证全部pass,但是cmd运行abaqus info=system找不到Fortran compiler ,Abaqus/Standard with user subroutine
  17. 用计算机亩换算成平方,亩换算平方(平方米换算亩计算器)
  18. 只有程序员才能看懂的趣图,第二个我就忍不住了哈哈哈哈!
  19. 2020.8.25 斗鱼Android开发二面面经
  20. 《发现你的心灵》——于丹

热门文章

  1. Word 中如何标记修订?如何去掉修订标记只显示最终状态?
  2. 数据结构实验一:多项式乘法问题
  3. 使用C语言获取指定域名的IP
  4. 【Linux】DHCP、FTP、DNS、WEB服务器的配置过程
  5. 自然语言处理入门实战2:基于深度学习的文本分类
  6. 机器学习笔记之——模型评估与改进之评估指标与评分
  7. 200万补贴!武汉市元宇宙产业创新发展方案申请条件、奖励补贴、流程
  8. python代码库能干什么_一行Python代码能做什么?
  9. n12.php解密,《信长之野望12革新》param.n12文件修改的一点翻译
  10. my.cnf 配置文件参数解释