【算法专场】分治(上)

news2025/1/11 3:59:01

目录

前言

什么是分治?

75. 颜色分类

算法分析

算法步骤

算法代码

912. 排序数组 - 力扣(LeetCode)

算法分析

算法步骤

算法代码

215. 数组中的第K个最大元素 - 力扣(LeetCode)

算法分析

算法步骤

​编辑 

算法代码

LCR 159. 库存管理 III - 力扣(LeetCode) 

算法分析

算法步骤

算法代码


前言

在前面,我们学习了八大排序,那么其中的快速排序和归并排序都用到了分治的思想。在算法中,有时候我们也需要利用分治的思想来解决一些算法问题。本篇我们主要讲解快速排序。

什么是分治?

分治算法是一种算法设计策略,将大问题转化为小问题,再将小问题转化为更小的问题,通过解决子问题来大问题。也就是说,把问题分解成若干个规模较小的问题,然后通过递归的方法来解决这些子问题,最后将子问题合并起来得到想要的结果。

步骤:

  1. 分解:将问题分解成若干个较小且独立的子问题,一般是通过递归实现;
  2. 解决:分解成小问题之后,在每个子问题中解决问题需求
  3. 归并:把问题解决完之后,将子问题进行合并。

接下来,我们就来通过一些练习来加深对分治思想的理解。

75. 颜色分类

算法分析

这道题的话就是要求我们将0、1、2这三个数依次从小排到大,那么对于这道题的话,其实我们有好几种排序方法都可以解决这道题,甚至我们可以使用java中的Arrays.sort()方法都可以解决,但是这里是不允许的。我们这里可以使用分治的思想来解决这道题。

算法步骤

算法代码

class Solution {
    /**
     * 交换数组中的两个元素
     * 
     * @param arr 数组
     * @param left 左侧元素的索引
     * @param right 右侧元素的索引
     */
    public void swap(int[] arr, int left, int right) {
        int tmp = arr[left];
        arr[left] = arr[right];
        arr[right] = tmp;
    }

    /**
     * 对颜色进行排序,将0放到数组的左边,2放到数组的右边,1保持原位
     * 
     * @param nums 需要排序的颜色数组,其中的颜色用0、1、2表示
     */
    public void sortColors(int[] nums) {
        int n = nums.length;
        int i = 0, left = -1, right = n;
        // 遍历数组,根据元素的值进行交换,最终达到0在左边,2在右边的目的
        while (i < right) {
            if (nums[i] == 0) {
                swap(nums, i++, ++left);
            } else if (nums[i] == 2) {
                swap(nums, i, --right);
            } else {
                i++;
            }
        }
    }
}

时间复杂度为O(n),空间复杂度为O(1). 

912. 排序数组 - 力扣(LeetCode)

算法分析

对于这种排序的题目,其实我们有很多种排序的方法可以解决,但是我们这里只讲如何使用分治的思想来解决这些排序题。 

算法步骤

对于这道题,我们可以采用分治的思想来解决,将数组划分为n个子数组,并且在n个子数组中使用类似快排的步骤来进行排序。同时我们需要注意:快排在趋近有序的情况下的时间复杂度为O(n^2),所以我们可以采用优化方法,如三数取中法,随机取值方法,这里我们采用的是随机取值法,使得算法的时间步骤度降为O(N*logN)

算法代码

/**
 * Solution 类用于提供一种基于快速排序的数组排序解决方案
 */
class Solution {
    /**
     * 对数组进行快速排序
     * 
     * @param nums 待排序的整数数组
     * @return 排序后的数组
     */
    public int[] sortArray(int[] nums) {
        qsort(nums, 0, nums.length - 1);
        return nums;
    }

    /**
     * 交换数组中两个指定位置的元素
     * 
     * @param nums 整数数组
     * @param left 左侧位置索引
     * @param right 右侧位置索引
     */
    public void swap(int[] nums, int left, int right) {
        int temp = nums[left];
        nums[left] = nums[right];
        nums[right] = temp;
    }

    /**
     * 使用快速排序算法对数组进行排序
     * 
     * @param nums 待排序的整数数组
     * @param left 排序开始的左边界索引
     * @param right 排序结束的右边界索引
     */
    public void qsort(int[] nums, int left, int right) {
        if (left >= right) return;
        int key = nums[new Random().nextInt(right - left + 1) + left];
        int i = left, L = left - 1, R = right + 1;
        while (i < R) {
            if (nums[i] < key) swap(nums, ++L, i++);
            else if (nums[i] == key) i++;
            else swap(nums, i, --R);
        }
        qsort(nums, left, L);
        qsort(nums, R, right);
    }
}

215. 数组中的第K个最大元素 - 力扣(LeetCode)

算法分析

这道题其实就是TOP-K问题,我们可以使用优先级队列(堆)的方法来解决这个问题:首先我们可以创建一个小根堆,在这个小根堆中放入k个元素,接着遍历剩余的n-k个元素,查看堆顶元素是不是小于数组中的元素,若小于则进行替换。当然,我们这里主要讲分治思想,那么我们同样是利用快排来解决这道题。

算法步骤

算法代码

/**
 * Solution类用于解决寻找数组中第k大的元素的问题
 */
class Solution {
    /**
     * 寻找数组中第k大的元素
     * 
     * @param nums 输入的整数数组
     * @param k 指定的第k大元素
     * @return 数组中第k大的元素
     */
    public int findKthLargest(int[] nums, int k) {
        // 调用快速排序相关函数来寻找第k大的元素
        return qsort(nums, 0, nums.length - 1, k);
    }

    /**
     * 快速排序算法的实现,用于寻找第k大的元素
     * 
     * @param nums 输入的整数数组
     * @param l 排序区间的左边界
     * @param r 排序区间的右边界
     * @param k 指定的第k大元素
     * @return 第k大的元素
     */
    private int qsort(int[] nums, int l, int r, int k) {

        // 如果左右指针相遇,直接返回该位置的元素
        if(l == r) return nums[l];

        // 随机选择一个基准值
        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) swap(nums, i, --right);
            else i++;
        }

        // 根据分区结果,决定下一步的查找范围
        int b = right - left - 1; // 等于基准值的区域大小
        int c = r - right + 1; // 大于基准值的区域大小
        if(c >= k) return qsort(nums, right, r, k); // 如果第k大在大于基准值的区域
        else if(b + c >= k) return key; // 如果第k大在等于基准值的区域
        return qsort(nums, l, left, k - b - c); // 否则在小于基准值的区域继续查找
    }

    /**
     * 交换数组中两个元素的位置
     * 
     * @param nums 输入的整数数组
     * @param i 第一个元素的索引
     * @param j 第二个元素的索引
     */
    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

LCR 159. 库存管理 III - 力扣(LeetCode)

算法分析

本道题其实与前面的找第k个最大元素类似,我们依旧可以使用排序,然后有另一个数组记录[0,k]期间的数,但本道题我们可以采用分治的思想,利用快排来解决。

算法步骤

当我们完成上述的过程后,我们需要利用一个大小为k的数组ret来接收nums数组中【0,k】区间的数.

算法代码

class Solution {
    /**
     * 库存管理函数,通过快速排序算法对库存进行管理
     *
     * @param stock 库存数据数组
     * @param cnt 需要管理的库存项数量
     * @return 管理后的库存数组
     */
    public int[] inventoryManagement(int[] stock, int cnt) {
        // 使用快速排序对库存数组进行排序
        qsort(stock, 0, stock.length - 1, cnt);

        // 创建一个新的数组来存储管理后的库存数据
        int[] ret = new int[cnt];
        // 将排序后的库存数据的前cnt个元素复制到新的数组中
        for(int i=0;i<cnt;i++) {
            ret[i] = stock[i];
        }

        // 返回管理后的库存数组
        return ret;
    }

    /**
     * 交换数组中两个元素的位置
     *
     * @param nums 数组
     * @param left 左侧元素索引
     * @param right 右侧元素索引
     */
    public void swap(int[] nums, int left, int right){
        int temp = nums[left];
        nums[left] = nums[right];
        nums[right] = temp;
    }

    /**
     * 快速排序算法的实现
     *
     * @param nums 待排序的数组
     * @param left 排序开始的左侧索引
     * @param right 排序结束的右侧索引
     * @param k 需要管理的库存项数量,用于决定排序的范围
     */
    private void qsort(int[] nums, int left, int right, int k){
        if(left >= right) return;
        int key = nums[new Random().nextInt(right - left + 1) + left];
        int i = left, L = left - 1, R = right + 1;
        while(i < R){
            if(nums[i]<key) swap(nums,++L,i++);
            else if(nums[i]==key) i++;
            else swap(nums,i,--R);
        }

        // 根据分区结果,决定下一步的查找范围
        int a=L-left+1;
        int b=R-L-1;
        if(a>=k) qsort(nums,left,L,k);
        else if(a+b>=k) return;
        else qsort(nums,R,right,k-a-b);
    }
}

以上就是采用分治思想使用快排的一些题目。

本篇就先到这里啦~下一篇将为大家讲解采用归并排序如何解决一些算法题目。

若有不足,欢迎指正~

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2131574.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Redis入门到精通一】什么是Redis?

目录 Redis 1. Redis的背景知识 2.Redis特性 3.Redis的使用场景 4.Ubuntu上安装配置Redis Redis Redis在当今编程技术中的地位可以说非常重要&#xff0c;大多数互联网公司内部都在使用这个技术&#xff0c;熟练使用Redis已经成为开发人员的一个必备技能。本章将带领读者…

yolov5实战全部流程

本科生阶段除了在中等以上的985和某些特定的CS强项院校&#xff0c;无意愿研究生学习的本科生是不建议学习人工智能这一专业的&#xff0c;保研学生也许可以在实验室打工推荐信学习接触到此类事件&#xff0c;此项blog主要是对yolov5的实践性项目&#xff0c;yolov5作为最具有代…

python 函数 封装

封装 函数的参数是&#xff1a;变量 def 函数(参数):print(参数)if __name__ __main__:函数(参数)函数(参数2)函数的参数是&#xff1a; 字典 import requests# 定义一个字典 data {} 地址 "https://webdriveruniversity.com/" 请求方法 getdata["url"…

【数据结构】选择题错题集

这里注意原本p后面也是有节点的。 这里只有遍历前面的链表找到尾节点连接即可。 快排是交换排序。 不要想象只有这两个节点&#xff0c;还有其他节点省略了。 筛选法就是向下调整算法。用向下调整建堆从最后一个节点的父亲开始。 这里错位相减法是乘4&#xff0c;所以最后要除三…

超详细!外婆都能看懂的Stable Diffusion入门教程,AI绘画SD零基础入门到精通教程!

一、前言 如今的AI绘画界有两大最强工具&#xff0c;一个是Midjourney &#xff0c;一个是StableDiffusion。Midjourney生成图片的质量非常高&#xff0c;可问题就是 Midjourney 的图片怎么精准的控制&#xff0c;或者是不改变某个物体的情况下更换背景等等&#xff0c;实在是…

虚拟化数据恢复—断电导致虚拟机目录项被破坏的数据恢复案例

虚拟化数据恢复环境&#xff1a; 某品牌服务器&#xff08;部署VMware EXSI虚拟机&#xff09;同品牌存储&#xff08;存放虚拟机文件&#xff09;。 虚拟化故障&#xff1a; 意外断电导致服务器上某台虚拟机无法正常启动。查看虚拟机配置文件发现这台故障虚拟机除了磁盘文件以…

视频监控平台是如何运作的?EasyCVR视频汇聚平台的高效策略与实践

随着科技的飞速发展&#xff0c;视频监控平台在社会安全、企业管理、智慧城市构建等领域发挥着越来越重要的作用。一个高效的视频监控平台&#xff0c;不仅依赖于先进的硬件设备&#xff0c;更离不开强大的视频处理技术作为支撑。这些平台集成了多种先进的视频技术&#xff0c;…

长短期记忆网络和UKF的结合|Python代码例程

结合长短期记忆网络(LSTM)和无迹卡尔曼滤波器(UKF)的技术在机器人导航和状态估计中具有广泛的应用前景。 文章目录 结合LSTM和UKF的背景结合LSTM和UKF的优势应用实例研究现状Python代码示例结合LSTM和UKF的背景 长短期记忆网络(LSTM)是一种特殊的递归神经网络(RNN),…

51单片机-IIC实验1-AT24C02数据存储(实战1)

本实验主要是针对IIC的具体案例进行实战&#xff0c;主要利用支持IIC通信的芯片AT24C02进行与51单片机构成通信。51&#xff08;AT89C52&#xff09;本身不带有IIC通信&#xff0c;所以&#xff0c;我们需要给51写一个IIC时序&#xff0c;以便与支持IIC协议的AT24C02数据存储芯…

逆向学习系列(三)Charles配合Drony的使用(真机)

在抓包中&#xff0c;有时可能出现无法抓包的情况&#xff0c;这时&#xff0c;可以尝试使用Drony转发抓包。 一、安装Drony 将电脑上的Drony_1.3.154_APKPure.apk复制粘贴进真机的Download文件夹中。在真机上找到这个apk&#xff0c;点击安装。 二、在VMOS中安装Drony 在真…

【Petri网导论学习笔记】Petri网导论入门学习(四)

Petri网导论入门学习&#xff08;四&#xff09; Petri 网导论学习笔记&#xff08;4&#xff09;1.2 标识网与网系统定义 1.8定义 1.9例 1.4存在空标识网的几种情况1.2 小结1.2学习完应达到的要求 Petri 网导论学习笔记&#xff08;4&#xff09; 如需学习转载请注明原作者并附…

55页可编辑PPT | 集团制造企业数字化转型顶层设计方案

这份PPT文档是一份关于集团制造企业数字化转型的顶层业务设计方案。文档详细介绍了企业在后ERP时代面临的挑战&#xff0c;以及如何通过Oracle解决方案来实现数字化转型。 数字化转型的三大要点集中在满足利益相关者的期望&#xff0c;以企业价值为核心引领业务模式的创新&…

DHCP协议原理大全与全局地址、接口地址池、中继代理三种方式配置

DHCP协议原理与配置 1.DHCP动态主机配置协议 原理:通过配置DHCP服务器给主机自动分配IP地址; 优点;1)可以动态学习或者获取IP地址及网络参数; 2)减少人工配置数量 3)减少ip抵制冲突; 4)采用客户端/服务器通信模式,报文基于UDP,服务器端端口号67。客户端端口号68…

AS608指纹识别模块(上位机操作)

目录 一、介绍 二、传感器原理 1.原理图 2.引脚描述 3.工作原理&#xff1a;模块指令格式 4.工作原理&#xff1a;模块应答格式 5.工作原理步骤 三、程序设计 四、实验效果 五、资料获取 项目分享 一、介绍 AS608模块采用了国内著名指纹识别芯片公司杭州晟元芯片技…

灵活连接,无限可能—探索EtherCAT的拓扑艺术

EtherCAT技术具备快速响应和高效率的特点&#xff0c;在工业自动化领域显得至关重要&#xff0c;其灵活的拓扑结构是其核心优势&#xff0c;支持多样化的网络布局&#xff0c;无需交换机或集线器&#xff0c;简化布线&#xff0c;降低成本&#xff0c;提高系统可靠性和灵活性。…

【AI大模型】ChatGPT模型原理介绍(上)

目录 &#x1f354; 什么是ChatGPT&#xff1f; &#x1f354; GPT-1介绍 2.1 GPT-1模型架构 2.2 GPT-1训练过程 2.2.1 无监督的预训练语言模型 2.2.2 有监督的下游任务fine-tunning 2.2.3 整体训练过程架构图 2.3 GPT-1数据集 2.4 GPT-1模型的特点 2.5 GPT-1模型总结…

2024年PMP我可以自学通过考试吗?

作为PMP考试的老考生&#xff0c;我想提醒一下&#xff0c;PMP考试费用很高&#xff0c;初次考试费用为3900元&#xff08;重考费用为2500元&#xff09;。如果你想自学PMP&#xff0c;一定要三思而后行。首先要问问自己是否符合以下几种情况&#xff1a; 1. 有相关的工作经验…

软考中级哪个科目比较简单,只为拿证?

软考不仅仅是为了拿证&#xff0c;选考科目也很重要。我建议你考虑软考中级的系统集成项目管理工程师。这个职称是由国家人力资源和社会保障部、工业和信息化部领导进行的国家级考试&#xff0c;通过考试后可以获得相应的证书。 1、通过率高 系统集成项目管理工程师属于中级职…

JDBC笔记

文章目录 准备MySQL数据的建立和建表 idea 建工程和模块设置属性配置文件编写JDBC代码URL的设置JDBC 代码配置文件 准备MySQL 数据的建立和建表 idea 建工程和模块 设置属性配置文件 编写JDBC代码 URL的设置 JDBC 代码 package com.yanyu;import java.sql.*; import java.util…

喜报 | 博睿数据荣获“绿色领导力董秘标杆之星”、“信息技术服务创新标杆之星”

9月12日&#xff0c;2024年中国国际服务贸易交易会在北京国家会议中心和首钢园区拉开序幕。作为服贸会的重要组成部分&#xff0c;9月12日下午&#xff0c;经济观察报经观传媒联合北京国际经济管理技术促进会、中国国际经济合作学会对外交流合作委员会在国家会议中心举办了“20…