分治法(算法)

这篇具有很好参考价值的文章主要介绍了分治法(算法)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

分治法是算法常用的解题方法之一,是将一个大的问题拆分为若干小的问题。二分法就是常用的分治法。

可以采用分治法解决的一些问题:

1.二分查找

2.合并排序(归并排序)

3.快速排序

4.快速幂

5.汉诺塔

一、二分查找

二分查找对要查找的序列有两个要求:

​ 一是该序列必须是有序的(即该序列中的所有元素都是按照大小关系排好序的,升序和降序都可以)

​ 二是该序列必须是顺序存储的。

例题:二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

思路:

1、先确定中间位置:

    middle = (left+right)/2;

2、将待查找得值与nums[middle]的值相比较。若相等,则查找成功并返回该位置,否则须确定新确定查找区间,继续查找。

3、如果nums[middle] 的值大于待查找的值,则证明在nums[middle]~nums[right]中所有的值都大于待查找的值,令right=middle,在nums[left]到nums[middle]中查找。

4、当left>right时,证明nums中没有要查找的值,跳出循环,返回-1。

代码实现

class Solution {

  public int search(int[] nums, int target) {

​    int left=0;

​    int right=nums.length-1;

​    int middle;

​    while(left<=right){

​      middle=(right+left)/2;

​      if(nums[middle]==target)

​        return middle;

​      else if(nums[middle]>target)

​        right=middle-1;

​      else

​        left=middle+1;

​    }

​    return -1;

  }

}

java

二、合并排序(归并排序)

归并排序是基于递归实现的,归并排序是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法的一个非常典型的应用。将数据分为a,b两组,再将a,b各自再分成两组,以此类推,当每一组都只有一个数据时,认为这个小小组已经达到了有序,再将相邻两个小小组依次合并。

例题:排序数组

给你一个整数数组 nums,请你将该数组升序排列。

示例 1:

输入:nums = [5,2,3,1]
输出:[1,2,3,5]

思路:

分治法,个人总结,算法,java,算法,排序算法

1、将数组进行拆分,利用递归的方法,将数组拆分成一个个单独的元素。

2、依次对数组进行合并,依次比较数组内的元素,将较小的元素先加入新的数组,依次往下比较,如果一个数组内的值已经全都加入新数组,将另一个数组的剩下的值依次加入新数组。

3、将额外的空间覆盖掉原来的空间。

代码实现

class Solution {
    int[] tmp; //定义临时数组

    public int[] sortArray(int[] nums) {
        tmp = new int[nums.length];
        mergeSort(nums, 0, nums.length - 1); //进入递归
        return nums;
    }

    public void mergeSort(int[] nums, int l, int r) {
        if (l >= r) {
            return;        //当l>=r时,每个区间里面只有一个数值
        }
        int mid = (l + r) /2;    //均分区间
        mergeSort(nums, l, mid);    //对左侧区间进行划分
        mergeSort(nums, mid + 1, r); //对右侧区间进行划分
        int i = l, j = mid + 1;    
        int cnt = 0;
        while (i <= mid && j <= r) { //利用循环将较两个区间内较小值依次加入临时数组
            if (nums[i] <= nums[j]) {
                tmp[cnt++] = nums[i++];
            } else {
                tmp[cnt++] = nums[j++];
            }
        }
        while (i <= mid) {                //将数组内剩下的元素依次加入
            tmp[cnt++] = nums[i++];
        }
        while (j <= r) {
            tmp[cnt++] = nums[j++];
        }
        for (int k = 0; k < r - l + 1; ++k) {    //将临时数组内的值存入nums
            nums[k + l] = tmp[k];
        }
    }
}

java

三、快速排序

快速排序,基于冒泡排序移动换位思想——通过遍历,判断每个数并放置在数组合适的位置。快速排序可能是应用最广泛的排序算法,适用于各种不同的输入数据且在一般应用中比其他排序都要快的多。

排序方式:

1、选定一个值,一般是数值的第一个值

2、进行分区,将该值与数组后面的数据依次进行比较,将比它小的值都放在左边,比它大的值都放在右边。

3、采用递归的方法,对该值左右区间的数组依次再进行分区操作,直到每个区间只剩一个值。

例题:最小的k个数

输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

示例 1:

输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]

思路:

1、选取一个基数

2、设置i,j两个指针,分别从左右两边向中间进行查找,先使j移动,当遇到arr[j]小于基数时,移动i,当遇到arr[i]大于基数时,将arr[i]与arr[j]互换位置,保证比基数小的值在左边,比基数大的值在右边

3、当i>=j的时候,跳出循环,将基数与i指针所在的位置交换数值

4、当i>k时,证明最小的k个数在0~(i-1)之间,在该区间查找最小的k个数

5、当i<k时,证明比基数大的一些数也是最小的k个数,在比基数大的值中间属于最小的k个数的值

6、当i==k时,返回最小的k个数

代码实现:

class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        if (k >= arr.length) return arr;
        return quickSort(arr, k, 0, arr.length - 1);//进入排序
    }
    //令arr[l]为基数
    private int[] quickSort(int[] arr, int k, int l, int r) {
        int i = l, j = r;
        while (i < j) {                    //当i<j时,
            while (i < j && arr[j] >= arr[l]) j--; 
            while (i < j && arr[i] <= arr[l]) i++;
            swap(arr, i, j);
        }
        swap(arr, i, l); //将基础值与arr[i]交换位置,保证在基础值左边的值均小于它,右边的值均大于它
        if (i > k) return quickSort(arr, k, l, i - 1); //当i>k时,证明最小的k个数在0~(i-1)之间,该区间的数进行排序
        if (i < k) return quickSort(arr, k, i + 1, r);//当i<k时,证明比基数大的一些数是最小的k个数,在比基数大的值中间属于最小的k个数的值
        return Arrays.copyOf(arr, k);
    }
    private void swap(int[] arr, int i, int j) { //将arr[i]和arr[j]中的值进行交换
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}

四、快速幂

例题:Pow(x, n)

实现 pow(x, n) ,即计算 x 的整数 n 次幂函数(即,xn )。

示例 1:

输入:x = 2.00000, n = 10
输出:1024.00000

思路

分治法,个人总结,算法,java,算法,排序算法

1、声明数据类型为long的b,将n赋值给它

2、当b为负数时,先将b转化为正数运算,x=1/x,b=-b

3、将b除以2,如果余数为一,将res=res*x,x等于x的平方,因为最后结果永远等于x的b次幂乘res,当b=0时,最后结果等于1乘res,即res

代码实现

class Solution {
    public double myPow(double x, int n) {
        long b = n;  //1、声明数据类型为long的b,将n赋值给它
        double res = 1.0;
        if(b < 0) {  //当b为负数时,转化为正数的运算,x=1/x,b=-b
            x = 1 / x;
            b = -b;
        }
        while(b > 0) {        //3、将b除以2,如果余数为一,将res=res*x,因为最后结果永远等于x的b次幂乘res,当b=0时,最后结果等于1乘res,即res
            if((b % 2) == 1) 
                res *= x;
            x *= x;
            b = b/2;
        }
        return res;
    }
}

五、汉诺塔

例题:汉诺塔问题

在经典汉诺塔问题中,有 3 根柱子及 N 个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自上而下按升序依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面)。移动圆盘时受到以下限制:
(1) 每次只能移动一个盘子;
(2) 盘子只能从柱子顶端滑出移到下一根柱子;
(3) 盘子只能叠在比它大的盘子上。

请编写程序,用栈将所有盘子从第一根柱子移到最后一根柱子。

你需要原地修改栈。

示例1:

输入:A = [2, 1, 0], B = [], C = []
输出:C = [2, 1, 0]

思路:

假设A柱有n个盘子

分治法,个人总结,算法,java,算法,排序算法

1、B柱与C柱替换,新的C柱就是B柱。

2、将A柱上的n-1个盘子移到新C柱上,实际上都移到了B柱上。

3、将B柱与C柱换回来。

4、将A柱上的最后一个盘子移到C柱上,这个盘子不用再移动,将它和C柱看成一个整体。

5、将B柱与A柱互换位置,B柱成为新的A柱。

6、将B柱看出A柱重复1~5步,直到盘子完全移到C上。

代码实现:

class Solution {
    public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {
        int num = A.size();
        dac(num,A,B,C);
    }
    //num为A盘剩下的盘子数量
    public void dac(int num,List<Integer> A,List<Integer> B,List<Integer> C){
        if(num == 1){    //当A盘只剩下一个盘子的时候,将最后一个盘子移动到C盘
            C.add(A.remove(A.size() - 1));
            return;
        }else{
            dac(num - 1,A,C,B); //B柱与C柱替换,新的C柱就是B柱,将A柱上的n-1个盘子移到新C柱上,实际上都移到了B柱上。
            C.add(A.remove(A.size() - 1));    //将A柱最后一个盘子移动到C柱上
            dac(num - 1,B,A,C); //将B柱与A柱互换位置,B柱成为新的A柱,将B柱上的所有盘子都移到C柱上
        }
    }
}

分治和递归:

递归和分治本身就不是同一种东西,递归是敲代码的技巧之一,分治是算法的思想之一,两者没关系。文章来源地址https://www.toymoban.com/news/detail-781391.html

到了这里,关于分治法(算法)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【leetcode刷题之路】剑指Offer(4)——分治+排序算法+动态规划

    8 分治算法 8.1 【递归】剑指 Offer 07 - 重建二叉树 https://leetcode.cn/problems/zhong-jian-er-cha-shu-lcof/   前序遍历是根左右,中序遍历是左根右,这也就意味着前序遍历的第一个节点是整棵树的根节点,顺着这个节点找到它在中序遍历中的位置,即为in_root,那么in_root左边的都在左子

    2024年02月11日
    浏览(42)
  • 分治与减治算法实验: 排序中减治法的程序设计

    目录 前言 实验内容 实验目的 实验分析 实验过程 流程演示 写出伪代码 实验代码 代码详解 运行结果 总结 本文介绍了算法实验排序中减治法的程序设计。减治法是一种常用的算法设计技术,它通过减少问题的规模来求解问题。减治法可以应用于排序问题,例如插入排序、选

    2023年04月27日
    浏览(25)
  • 分治与减治算法实验:题目2 排序中分治法的程序设计

    目录 前言: 一、实验内容 二、实验目的 三、实验步骤 四、实验过程 1、算法分析 2、写出伪代码 3、代码实现 4、代码详解 5、用例测试 6、复杂度分析 总结 分治法是一种将复杂问题分解为若干个相同或相似的子问题,然后递归地求解子问题,最后将子问题的解合并为原问题

    2023年04月25日
    浏览(28)
  • Java中常用算法及示例-分治、迭代、递归、递推、动态规划、回溯、穷举、贪心

    1、分治算法的基本思想是将一个计算复杂的问题分成规模较小、计算简单的小问题求解, 然后综合各个小问题,得到最终答案。 2、穷举(又称枚举)算法的基本思想是从所有可能的情况中搜索正确的答案。 3、迭代法(Iterative Method) 无法使用公式一次求解,而需要使用重复结构

    2024年02月08日
    浏览(34)
  • 【课设】java:迷宫小游戏(递归与分治、动态规划、贪心算法、回溯法、分支限界法)

    鱼弦:CSDN内容合伙人、CSDN新星导师、全栈领域优质创作者 、51CTO(Top红人+专家博主) 、github开源爱好者(go-zero源码二次开发、游戏后端架构 https://github.com/Peakchen) 递归与分治算法 原理: 递归与分治算法将问题分解为子问题,递归地解决每个子问题,最后将结果合并得到整

    2024年02月02日
    浏览(27)
  • DSt:数据结构的最强学习路线之数据结构知识讲解与刷题平台、刷题集合、问题为导向的十大类刷题算法(数组和字符串、栈和队列、二叉树、堆实现、图、哈希表、排序和搜索、动态规划/回溯法/递归/贪心/分治)总

    Algorithm:【算法进阶之路】之算法面试刷题集合—数据结构知识和算法刷题及其平台、问题为导向的十大类刷题算法(数组和字符串、链表、栈和队列、二叉树、堆、图、哈希表、排序和搜索、回溯算法、枚举/递归/分治/动态规划/贪心算法)总结 目录 相关文章

    2024年02月08日
    浏览(43)
  • 算法-分治算法

    文章来源: https://blog.csdn.net/weixin_45630258/article/details/126425400 欢迎各位大佬指点、三连 1、定义:分治,也就是分而治之。 它的一般步骤是: ① 将原问题分解成若干个规模较小的子问题(子问题和原问题的结构一样,只是规模不一样) ② 子问题又不断分解成规模更小的子问

    2024年02月09日
    浏览(27)
  • 十大排序算法及Java中的排序算法

    常见的排序算法有十种,可以分为以下两大类: 非线性时间比较类排序 :通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(n log n),因此称为非线性时间比较类排序 线性时间非比较类排序 :不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时

    2024年02月08日
    浏览(34)
  • JAVA算法(二)排序算法

    定义:相邻的数据两两比较,小的 放前面,大的放后面 过程: 相邻的元素两两比较,小的放左边,大的放右边。 第一轮比较完毕之后,最大值就已经确定,第二轮可以少循环一次,后面以此类推。 如果数组中有n个数据,总共我们只要执行n-1轮的代码就可以。 定义: 从0索

    2024年02月05日
    浏览(28)
  • Java 与排序算法(1):冒泡排序

    冒泡排序(Bubble Sort)是一种简单的排序算法,它的基本思想是通过不断交换相邻两个元素的位置,使得较大的元素逐渐往后移动,直到最后一个元素为止。冒泡排序的时间复杂度为 O ( n 2 ) O(n^2) O ( n 2 ) ,空间复杂度为 O ( 1 ) O(1) O ( 1 ) ,是一种稳定的排序算法。 其实现过程

    2024年02月11日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包