【数据结构与算法】(22)高级数据结构与算法设计之 Divide and Conquer 分治法 代码示例与详细讲解

目录

    • 4.4 Divide and Conquer
      • 1) 概述
        • 二分查找
        • 快速排序
        • 归并排序
        • 合并K个排序链表 - LeetCode 23
        • 对比动态规划
      • 2) 快速选择算法
        • 数组中第k个最大元素-Leetcode 215
        • 数组中位数
      • 3) 快速幂-Leetcode 50
      • 4) 平方根整数部分-Leetcode 69
      • 5) 至少k个重复字符的最长子串-Leetcode 395

在这里插入图片描述

4.4 Divide and Conquer

1) 概述

分治思想

  • 将大问题划分为两个到多个子问题
  • 子问题可以继续拆分成更小的子问题,直到能够简单求解
  • 如有必要,将子问题的解进行合并,得到原始问题的解

之前学过的一些经典分而治之的例子

  • 二分查找
  • 快速排序
  • 归并排序
  • 合并K个排序链表 - LeetCode 23
二分查找

在这里插入图片描述

public static int binarySearch(int[] a, int target) {return recursion(a, target, 0, a.length - 1);
}public static int recursion(int[] a, int target, int i, int j) {if (i > j) {return -1;}int m = (i + j) >>> 1;if (target < a[m]) {return recursion(a, target, i, m - 1);} else if (a[m] < target) {return recursion(a, target, m + 1, j);} else {return m;}
}

减而治之,每次搜索范围内元素减少一半

快速排序

在这里插入图片描述

public static void sort(int[] a) {quick(a, 0, a.length - 1);
}private static void quick(int[] a, int left, int right) {if (left >= right) {return;}int p = partition(a, left, right);quick(a, left, p - 1);quick(a, p + 1, right);
}

分而治之,这次分区基准点,在划分后两个区域分别进行下次分区

归并排序

在这里插入图片描述

public static void sort(int[] a1) {int[] a2 = new int[a1.length];split(a1, 0, a1.length - 1, a2);
}private static void split(int[] a1, int left, int right, int[] a2) {int[] array = Arrays.copyOfRange(a1, left, right + 1);// 2. 治if (left == right) {return;}// 1. 分int m = (left + right) >>> 1;split(a1, left, m, a2);                 split(a1, m + 1, right, a2);       // 3. 合merge(a1, left, m, m + 1, right, a2);System.arraycopy(a2, left, a1, left, right - left + 1);
}

分而治之,分到区间内只有一个元素,合并区间

合并K个排序链表 - LeetCode 23
public ListNode mergeKLists(ListNode[] lists) {if (lists.length == 0) {return null;}return split(lists, 0, lists.length - 1);
}public ListNode split(ListNode[] lists, int i, int j) {System.out.println(i + " " + j);if (j == i) {return lists[i];}int m = (i + j) >>> 1;return mergeTwoLists(split(lists, i, m),split(lists, m + 1, j));
}

分而治之,分到区间内只有一个链表,合并区间

对比动态规划
  • 都需要拆分子问题
  • 动态规划的子问题有重叠、因此需要记录之前子问题解,避免重复运算
  • 分而治之的子问题无重叠

2) 快速选择算法

public class Utils {static int quick(int[] a, int left, int right, int index) {int p = partition(a, left, right);if (p == index) {return a[p];}if (p < index) {return quick(a, p + 1, right, index);} else {return quick(a, left, p - 1, index);}}static int partition(int[] a, int left, int right) {int idx = ThreadLocalRandom.current().nextInt(right - left + 1) + left;swap(a, left, idx);int pv = a[left];int i = left + 1;int j = right;while (i <= j) {// i 从左向右找大的或者相等的while (i <= j && a[i] < pv) {i++;}// j 从右向左找小的或者相等的while (i <= j && a[j] > pv) {j--;}if (i <= j) {swap(a, i, j);i++;j--;}}swap(a, j, left);return j;}static void swap(int[] a, int i, int j) {int t = a[i];a[i] = a[j];a[j] = t;}
}
数组中第k个最大元素-Leetcode 215
public class FindKthLargestLeetcode215 {/*目标 index = 43   2   1   5   6   4=>  3   2   1   4   5   6   (3)=>  3   2   1   4   5   6   (5)=>  3   2   1   4   5   6   (4)*/public int findKthLargest(int[] a, int k) {return Utils.quick(a, 0, a.length - 1, a.length - k);}public static void main(String[] args) {// 应为5FindKthLargestLeetcode215 code = new FindKthLargestLeetcode215();System.out.println(code.findKthLargest(new int[]{3, 2, 1, 5, 6, 4}, 2));// 应为4System.out.println(code.findKthLargest(new int[]{3, 2, 3, 1, 2, 4, 5, 5, 6}, 4));}
}
数组中位数
public class FindMedian {/*偶数个3   1   5   4奇数个4   5   14   5   1   6   3*/public static double findMedian(int[] nums) {if (nums.length % 2 != 0) {return findIndex(nums, nums.length / 2);} else {System.out.println((nums.length / 2 - 1) + "," + (nums.length / 2));int a = findIndex(nums, nums.length / 2);int b = findIndex(nums, nums.length / 2 - 1);return (a + b) / 2.0;}}public static void main(String[] args) {System.out.println(findMedian(new int[]{3, 1, 5, 4}));System.out.println(findMedian(new int[]{3, 1, 5, 4, 7, 8}));System.out.println(findMedian(new int[]{4, 5, 1}));System.out.println(findMedian(new int[]{4, 5, 1, 6, 3}));}static int findIndex(int[] a, int index) {return Utils.quick(a, 0, a.length - 1, index);}}

3) 快速幂-Leetcode 50

public class QuickPowLeetcode50 {/*2^10/         \2^5         2^5/  \        /  \2 2^2 2^2    2 2^2 2^2/ \  / \     / \  / \2  2  2  2   2  2  2  2256          n=1 x=65536 mul=1024/         \16          16          n=2 x=256 mul=4/  \        /  \2 4    4    2  4    4       n=5  x=16 mul=4/ \  / \     / \  / \2  2  2  2   2  2  2  2     n=10  x=4  mul=1*/static double myPow(double x, int n) {if (n == 0) {return 1;}double mul = 1;long N = n;if (n < 0) {N = -N;}while (N > 0) {if ((N & 1) == 1) {mul *= x;}x =  x * x;N = N >> 1;}return n > 0 ? mul : 1 / mul;}static double myPow1(double x, int n) {long N = n;if (N < 0) {return 1.0 / rec(x, -N);}return rec(x, n);}static double rec(double x, long n) {if (n == 0) {return 1;}if (n == 1) {return x;}double y = rec(x, n / 2);if ((n & 1) == 1) {return x * y * y;}return y * y;}public static void main(String[] args) {System.out.println(myPow(2, 10));  // 1024.0System.out.println(myPow(2.1, 3)); // 9.261System.out.println(myPow(2, -2)); // 0.25System.out.println(myPow(2, 0)); // 1.0System.out.println(myPow(2, -2147483648)); // 1.0}
}

4) 平方根整数部分-Leetcode 69

public class SqrtLeetcode69 {static int mySqrt(int x) {int i = 1, j = x;int r = 0;while (i <= j) {int m = (i + j) >>> 1;if (x / m >= m) {r = m;i = m+1;} else {j = m-1;}}return r;}public static void main(String[] args) {System.out.println(mySqrt(1));System.out.println(mySqrt(2));System.out.println(mySqrt(4));System.out.println(mySqrt(8));System.out.println(mySqrt(9));}
}
  • while(i <= j) 含义是在此区间内,只要有数字还未尝试,就不算结束
  • r 的作用是保留最近一次当 m 2 < = x m^2 <= x m2<=x 的 m 的值
  • 使用除法而非乘法,避免大数相乘越界

5) 至少k个重复字符的最长子串-Leetcode 395

public class LongestSubstringLeetcode395 {static int longestSubstring(String s, int k) {// 子串落选情况if (s.length() < k) {return 0;}int[] counts = new int[26]; // 索引对应字符 值用来存储该字符出现了几次char[] chars = s.toCharArray();for (char c : chars) { // 'a' -> 0  'b' -> 1 ....counts[c - 'a']++;}System.out.println(Arrays.toString(counts));for (int i = 0; i < chars.length; i++) {char c = chars[i];int count = counts[c - 'a']; // i字符出现次数if (count > 0 && count < k) {int j = i + 1;while(j < s.length() && counts[chars[j] - 'a'] < k) {j++;}System.out.println(s.substring(0, i) + "\t" + s.substring(j));return Integer.max(longestSubstring(s.substring(0, i), k),longestSubstring(s.substring(j), k));}}// 子串入选情况return s.length();}public static void main(String[] args) {//                                         i jSystem.out.println(longestSubstring("aaaccbbb", 3)); // ababbSystem.out.println(longestSubstring("dddxaabaaabaacciiiiefbff", 3));
//        System.out.println(longestSubstring("ababbc", 3)); // ababb
//        System.out.println(longestSubstring("ababbc", 2)); // ababb/*ddd aabaaabaa iiii fbffaa aaa aa      f ff统计字符串中每个字符的出现次数,移除哪些出现次数 < k 的字符剩余的子串,递归做此处理,直至- 整个子串长度 < k (排除)- 子串中没有出现次数 < k 的字符*/}
}

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

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

相关文章

云原生之API网关Traefik

1. 前言 说到web服务的开源网关&#xff0c;我首先想到的是Nginx&#xff0c;最早使用的就是它&#xff0c;现在都还在使用它。系统上线了Docker Swarm集群之后&#xff0c;不继续使用Nginx直接做Docker服务的网关&#xff0c;是因为Nginx毕竟比Docker Swarm出现的早&#xff0…

简单实现文字滚动效果-CSS版本

先看看效果 话不多说直接上代码 <template><div class"main"><div class"scroll-region"><div class"swiper-scroll-content"><span class"list-btn" v-for"(item, index) in overviewList" :…

【基于Ubuntu20.04的Autoware.universe安装过程】方案二:双系统 | 详细记录 | 全过程图文 by.Akaxi

目录 一、Autoware.universe背景 Part-1&#xff1a;安装双系统教程 二、查看Windows引导方式 三、制作安装盘 四、设置电脑配置 1.关闭bitlocker 2.压缩硬盘分区 3.关闭Secure Boot 4.关闭intel RST 5.BIOS设置U盘引导 五、安装Ubuntu20.04 1.ventoy引导 2.安装配…

07 Redis之持久化(RDB(Redis DataBase) + 写时复制 + AOF(Append Only File)+混合持久化)

4 Redis持久化 Redis 是一个内存数据库&#xff0c;然而内存中的数据是不持久的&#xff0c;若主机宕机或 Redis 关机重启&#xff0c;则内存中的数据全部丢失。 当然&#xff0c;这是不允许的。Redis 具有持久化功能&#xff0c;其会按照设置以快照或操作日志的形式将数据持…

双重检查锁定与延迟初始化

双重检验锁&#xff1a;多线程下的单例模式。 懒加载模式&#xff1a;延迟初始化。

如何做到三天内完成智能直流伺服电机系统开发?

适应EtherCAT/CANopen协议三相伺服电机直流伺服电机直线伺服音圈电机 如何开发高性能直流伺服电机驱动控制器&#xff1f; 需要熟悉高性能单片机&#xff08;至少是ARM或DSP水平的&#xff09;&#xff0c;需要掌握空间磁场矢量控制FOC&#xff0c;需要掌握运动轨迹算法……此…

【03】逆序数组

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 一、逆序函数是什么&#xff1f; 二、逆序函数原码 1.直接逆序 2.创建临时数组逆序 三、结言 &#x1f4a5;一、逆序函数是什么&#xff1f; 示例&#xff1a;输入1 4 …

【MySQL面试复习】在MySQL中,如何定位慢查询?

系列文章目录 系列文章目录什么情况下需要定位慢查询&#xff1f;慢查询的一般表现形式是什么&#xff1f;如何定位慢查询&#xff1f; 什么情况下需要定位慢查询&#xff1f; 页面加载过慢、接口压测响应时间过长&#xff08;比如超过1s&#xff09; 慢查询的一般表现形式是什…

【MySQL面试复习】什么是聚簇索引(聚集索引)和非聚簇索引(二级索引)/什么是回表?

系列文章目录 在MySQL中&#xff0c;如何定位慢查询&#xff1f; 发现了某个SQL语句执行很慢&#xff0c;如何进行分析&#xff1f; 了解过索引吗&#xff1f;(索引的底层原理)/B 树和B树的区别是什么&#xff1f; 系列文章目录什么是聚簇索引&#xff08;聚集索引&#xff09…

SpringBootRest服务调用

目录 RestTemplate 依赖配置 自定义RestTemplate webCilent 依赖配置 自定义webCilent springboot中有两种方式实现Rest远程服务调用&#xff0c;分别是RestTemplate与webCilent。下面分别介绍一下这两种方式。 RestTemplate 依赖配置 RestTemplate是Spring Framework提供的…

蓝桥杯14届计算思维国赛U8组包含真题和答案

十四届蓝桥杯国赛考试计算思维 U8 组 答案在底部 第一题 以下选项中,( )是由美国计算机协会设立,对在计算机领域内作出重要贡献的个人授予的奖项 。A.图灵奖 C.菲尔兹奖 B.诺贝尔奖 D.普利策奖 第二题 希希去吃寿司。餐台上摆出了许多食物,可供大家自选。如下图所示。 …

在 where子句中使用子查询(二)

目录 ANY ANY &#xff1a;功能上与 IN 是没有任何区别的 >ANY &#xff1a;比子查询返回的最小值要大 ALL >AL &#xff1a;比子查询返回的最大值要大 EXISTS() 判断 NOT EXISTS Oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209…

设计模式学习笔记 - 面向对象 - 7.为什么要多用组合少用继承?如何决定该用组合还是继承?

前言 在面向对象编程中&#xff0c;有一条非常经典的设计原则&#xff1a;组合优于继承&#xff0c;多用组合少用继承。 为什么不推荐使用继承&#xff1f; 组合比继承有哪些优势&#xff1f; 如何判断该用组合还是继承&#xff1f; 为什么不推荐使用继承&#xff1f; 继承…

解决IDEA搜不到插件

File -> Settings -> Plugins https://plugins.jetbrains.com/ 完成以上操作即可搜到插件

化学分子Mol2文件格式与使用注意事项

欢迎浏览我的CSND博客&#xff01; Blockbuater_drug …点击进入 文章目录 前言一、Mol2文件示例二、 Mol2文件主要结构解释及注意事项MOLECULE 字段解释ATOM 字段解释BOND 字段解释SUBSTRUCTURE字段解释 总结参考资料 前言 Mol2格式文件是一个ASCII 文件&#xff0c;由Tripos…

【EAI 025】Ego4D: Around the World in 3,000 Hours of Egocentric Video

Paper Card 论文标题&#xff1a;Ego4D: Around the World in 3,000 Hours of Egocentric Video 论文作者&#xff1a;Kristen Grauman, Andrew Westbury, Eugene Byrne, et al. 作者单位&#xff1a;UC Berkeley, CMU, Google 论文原文&#xff1a;https://arxiv.org/abs/2110…

linux 文本编辑命令【重点】

目录 vi&vim介绍 vim安装 vim使用 查找命令 find grep 文本编辑的命令&#xff0c;主要包含两个: vi 和 vim vi&vim介绍 作用: vi命令是Linux系统提供的一个文本编辑工具&#xff0c;可以对文件内容进行编辑&#xff0c;类似于Windows中的记事本 语法: vi file…

在autodl搭建stable-diffusion-webui+sadTalker

本文介绍在autodl.com搭建gpu服务器&#xff0c;实现stable-diffusion-webuisadTalker功能&#xff0c;图片音频 可生成视频。 autodl租GPU 自己本地部署SD环境会遇到各种问题&#xff0c;网络问题&#xff08;比如huggingface是无法访问&#xff09;&#xff0c;所以最好的方…

中国象棋开源人工智能程序(带UI)搬运

我的老父亲一直想买一个人工智能象棋机器人陪他下棋&#xff0c;我就在Github上找了一个开源项目&#xff0c;带UI的中国象棋人工智能程序&#xff0c;其训练方法类似AlphaZero&#xff0c;因而叫Chinese Chess Zero (cczero)。虽然看起来很久没有维护了&#xff0c;但是棋力也…

SpringMVC 学习(六)之视图

目录 1 SpringMVC 视图介绍 2 JSP 视图 3 Thymeleaf 视图 4 FreeMarker 视图 5 XSLT 视图 6 请求转发与重定向 6.1 请求转发 (Forward) 6.2 重定向 (Redirect) 7 视图控制器 (view-controller) 1 SpringMVC 视图介绍 在 SpringMVC 框架中&#xff0c;视图可以是一个 J…