我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java举例讲解分治算法思想

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java举例讲解分治算法思想

分治算法

什么是分治算法

顾名思义就是分而治之,分治法可以用来解决各种问题,是一种将复杂难解的问题分割成规模和结构相同或者相似的子问题,通过对简单子问题的求解而达到对原问题的求解目的的算法设计方法,在求解一个复杂问题时可以将其分解成若干个子问题,子问题还可以进一步分解成更小的子子问题,直到解决的子问题是一些基本的问题,并且求解方法是已知的,可以直接求解为止。分而治之的策略不但能够使原本复杂的问题变得更加清晰,而且能够将问题的规模缩小而降低问题求解的难度。

分治算法的思想

对于一个规模较大的问题,可以将这个规模较大的问题分解为n个规模较小的相互独立且与原问题结构相同的子问题进行求解。首先通过递归来解决这些子问题,然后对子问题的解进行合并得到原问题的解,这中求解问题的思路就是分治法。

简单可以理解为

首先将原问题分解为若干个子问题

各子问题的结构基本相似,规模基本相当

递归使分治的工具

  • 递归调用:问题和子问题的分解
  • 递归约束:对子问题的解进行合并

分治法四大基本特征

  • 原问题的规模缩小到一定程度时可以很容易的被求解。
  • 原问题可以分解成若干个规模较小的同构子问题。这是使用分治法的前提,这个特征和递归的思想差不多,满足这个特征的问题通常称这个问题具有最优子结构性质。
  • 各问题的解可以合并为原问题的解
  • 原问题所分出的各个子问题之间是相互独立的,即子问题之间不包含公共的子问题,

分治法求解问题的三个基本步骤

  • 分解(递归调用):将原问题分解为若干个相互独立,规模较小且与原问题形式相同的一系列子问题。在使用分治算法时,最好使各子问题的规模大致相同。
  • 解决(对子问题求解):如果子问题的规模小到可以直接被解决则直接解决,否则需要递归求解各个子问题。
  • 合并(递归约束):将各个子问题的结果合并成原问题的解,有些问题的合并方法比较明显,有些问题的合并方法比较复杂,或者存在多种合并方案,有些问题的合并方案并不明显需要具体问题具体分析。

分治算法解决问题过程的伪代码

 divide-and-conquer(p)//阀值
 {
     if(|p|<n0)adhoc(p);//如果问题可以直接求解,就直接求解。|p|代表问题的规模
     divide p into amaller subinstances P1,P2,P3......Pk;//将原问题分解成k个规模较小的子问题,且这些子问题的规模相当结构相似
     for(i=1;i<=k;i++)
         yi=divide-and-conquer(p)//递归求解各个子问题Pi,若分解的子问题还可以分解成若干个子子问题,就再对子问题进行分解
         return merge(y1,y2,y3......yk)//将子问题的解合并成原问题的解
 }  

关于分治算法的举例

归并排序

归并排序算法是用分治策略实现对规模为n的记录序列进行排序的算法,基本思想是:待排序记录分成大小大致相同的两个或多个子集合,分别对子集合进行排序,最终将两个排序号的子集合合并成所要求的排序好的集合。

package 算法设计与分析;
 public class 归并排序 {
 //arr是存放原始元素的数组,left数组arr的最左边,left是数组的最右边,mid是划分的终点,数组tmp是一个临时数组,就是一个辅助存储空间
         public static void main(String[] args) {
             int[] arr = {49,38,65,97,76,13,27};
             int[] tmp = new int[arr.length];    //新建一个临时数组存放,相当于是一个辅助空间
             mergeSort(arr,0,arr.length-1,tmp);
             for(int i=0;i<arr.length;i++){
                 System.out.print(arr[i]+" ");
             }
         }
         public static void merge(int[] arr,int left,int mid,int right,int[] tmp){
             int i = 0;
             int j = left,k = mid+1;  //左边序列和右边序列起始索引
             while(j <= mid && k <= right){
                 if(arr[j] <= arr[k]){
                     tmp[i++] = arr[j++];
                 }else{
                     tmp[i++] = arr[k++];
                 }
             }
             //若左边序列还有剩余,则将其全部拷贝进tmp[]中
             while(j <= mid){
                 tmp[i++] = arr[j++];
             }
             while(k <= right){
                 tmp[i++] = arr[k++];
             }
             for(int t=0;t<i;t++){
                 arr[left+t] = tmp[t];
             }
         }
         public static void mergeSort(int[] arr,int left,int right,int[] tmp){
             if(left<right){
                 int mid = (left+right)/2;
                 mergeSort(arr,left,mid,tmp); //对左边序列进行归并排序
                 mergeSort(arr,mid+1,right,tmp);  //对右边序列进行归并排序
                 merge(arr,left,mid,right,tmp);    //合并两个有序序列,相当于用tmp覆盖原来的arr
             }
         }
     }

基本步骤

  • 划分中点mid;
  • 分别对左右子区间归并排序,归并的结果(是一个有序序列)存放在数组tmp中,tmp是一个临时数组,相当于一个辅助存储空间;
  • 用tmp去覆盖原来的数组arr。

快速排序

快速排序又称为交换排序,是冒泡排序的一种,在快速排序中,记录的比较和交换是从两端向中间进行的,关键字值较大的记录一次就能交换到后面单元,关键字值小的记录一次就能交换到前面单元,记录每次移动的距离较大,因而总的比较和移动次数较少。

思想:把最左边的元素作为主元,数组一左一右两个指针进行扫描,左边的指针直到找到一个元素比主元大时,便停止左移,右边的指针向左移动,直到找到一个不大于主元的元素,交换两个指针所指向的元素。

注意:这种排序要在左边设置一个较大的值作为哨兵,防止左指针在右移的过程中移出序列之外。

package 算法设计与分析;
 public class 快速排序 {
         public static void quickSort(int[] arr,int left,int right){
             int i,j,temp,t;
             if(left>right){
                 return;
             }
             i=left;
             j=right;
             //temp就是基准位,就是主元,将数组中的第一个元素作为主元
             temp = arr[left];
             while (i<j) {
                 //先看右边,依次往左递减
                 while (temp<=arr[j]&&i<j) {
                     j--;
                 }
                 //再看左边,依次往右递增
                 while (temp>=arr[i]&&i<j) {
                     i++;
                 }
                 //如果满足条件则交换
                 if (i<j) {
                     t = arr[j];
                     arr[j] = arr[i];
                     arr[i] = t;
                 }
             }
             //最后将基准为与i和j相等位置的数字交换
             arr[left] = arr[i];
             arr[i] = temp;
             //递归调用左半数组
             quickSort(arr, left, j-1);
             //递归调用右半数组
             quickSort(arr, j+1, right);
         }
         public static void main(String[] args){
             int[] arr = {72,26,57,88,42,80,72,48,60,};
             quickSort(arr, 0, arr.length-1);
             for (int i = 0; i < arr.length; i++) {
                 System.out.print(arr[i]+ " ");
             }
         }
     }

二分搜索算法

在一个表中搜索确定一个关键字值为给定的元素,若在表中存在这样的元素,则搜索成功,搜索结果可以返回整个数据的元素,也可以指示该元素在表中的位置,若表中不存在关键字值的元素,则搜索失败。

 package 算法设计与分析;
 //用递归的方法解决二分搜索问题
 public class 二分查找 {
     public static void main(String[] args) {
         int[] arr = {-7,-2,0,15,27,54,80,88,102};
         //想要查找的元素
         int key = 80;
         //对查找到的元素进行定位
         int position = Search(arr,key,0,arr.length - 1);
         if(position == -1){
             System.out.println("查找的是"+key+",序列中没有该数!");
         }else{
             System.out.println("查找的是"+key+",找到位置为:"+position);
         }
     }
     public static int Search(int[] arr,int key,int left,int right){
         if(key < arr[left] &&key > arr[right] &&left > right){
             return -1;
         }
         int middle = (left + right) / 2;            //初始中间位置
         if(arr[middle] > key){
             //比关键字大则关键字在左区域
             return Search(arr, key, left, middle - 1);
         }else if(arr[middle] < key){
             //比关键字小则关键字在右区域
             return Search(arr, key, middle + 1, right);
         }else {
             return middle;
         }
     }
 }

小结

以上就是针对分治算法的详细分析,分治算法在我们解决问题的过程中可以使我们的问题变得简单化,降低时间复杂度,利用分治法解决问题比较稳定。

到此这篇关于Java举例讲解分治算法思想的文章就介绍到这了,更多相关Java分治算法内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java举例讲解分治算法思想

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

java分治思想之ForkJoin详解

这篇文章主要为大家介绍了java分治思想之ForkJoin使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-05-18

基本算法思想:递归+分治+动态规划+贪

作者:心叶时间:2018-05-01 19:28本文对应github地址:https://github.com/yelloxing/...以上实现了常见算法的java、c语言、javascrpt(或node.js)、python3和go语言
2023-01-31

Java分治法与二分搜索算法实例分析

本文实例讲述了Java分治法与二分搜索算法。分享给大家供大家参考,具体如下:1、分治法分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相同。递归的解这些子问题,然后将各子问题的解合并得到原问题的
2023-05-30

Java基于分治法实现的快速排序算法示例

本文实例讲述了Java基于分治法实现的快速排序算法。分享给大家供大家参考,具体如下:package cn.nwsuaf.quick;public cl
2023-05-30

举例讲解Python中的身份运算符的使用方法

Python身份运算符 身份运算符用于比较两个对象的存储单元以下实例演示了Python所有身份运算符的操作:#!/usr/bin/pythona = 20 b = 20if ( a is b ):print "Line 1 - a and
2022-06-04

Java基于分治算法实现的棋盘覆盖问题示例

本文实例讲述了Java基于分治算法实现的棋盘覆盖问题。分享给大家供大家参考,具体如下:在一个2^k * 2^k个方格组成的棋盘中,有一个方格与其它的不同,若使用以下四种L型骨牌覆盖除这个特殊方格的其它方格,如何覆盖。四个L型骨牌如下图:棋盘
2023-05-30

Java数据结构与算法实例讲解

这篇文章主要讲解了“Java数据结构与算法实例讲解”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java数据结构与算法实例讲解”吧! 为什么需要树这种结构1.数组存储方式分析:优点:通过下标
2023-06-15

Java基于分治算法实现的线性时间选择操作示例

本文实例讲述了Java基于分治算法实现的线性时间选择操作。分享给大家供大家参考,具体如下:线性时间选择问题:给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素,(这里给定的线性集是无序的)。随机划分线性选择线性
2023-05-30

java排序算法之_选择排序(实例讲解)

选择排序是一种非常简单的排序算法,从字面意思我们就可以知道,选择就是从未排序好的序列中选择出最小(最大)的元素,然后与第 i 趟排序的第 i-1(数组中下标从 0 开始) 个位置的元素进行交换,第 i 个元素之前的序列就是已经排序好的序列。
2023-05-31

Java Zookeeper分布式分片算法超详细讲解流程

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等
2023-03-01

Java二分查找算法实例详解

在本篇文章里小编给大家分享总结的是一篇关于Java二分查找算法实例详解内容,对此有兴趣的朋友们可以跟着学习下。
2022-11-13

java算法之二分查找法的实例详解

java算法之二分查找法的实例详解原理假定查找范围为一个有序数组(如升序排列),要从中查找某一元素,如果该元素在此数组中,则返回其索引,否则返回-1。通过数组长度可取出中间位置元素的索引,将其值与目标值比较,如果中间位置元素值大于目标值,则
2023-05-31

java算法题解Leetcode763划分字母区间示例

这篇文章主要为大家介绍了java算法题解Leetcode763划分字母区间示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-01-09

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录