【数据结构与算法】Divide and Conquer

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 的字符*/}
}

本文,已收录于,我的技术网站 pottercoding.cn,有大厂完整面经,工作技术,架构师成长之路,等经验分享!

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

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

相关文章

【C语言】数组练习

【C语言】数组练习 练习1&#xff1a;多个字符从两端移动&#xff0c;向中间汇聚练习2、二分查找 练习1&#xff1a;多个字符从两端移动&#xff0c;向中间汇聚 编写代码&#xff0c;演示多个字符从两端移动&#xff0c;向中间汇聚 练习2、二分查找 在⼀个升序的数组中查找指…

国庆作业

day1 1.开发环境 Linux系统GCCFDBmakefilesqlite3 2.功能描述 项目功能: 服务器&#xff1a;处理客户端的请求&#xff0c;并将数据存入数据库中&#xff0c;客户端请求的数据从数据库进行获取&#xff0c;服务器转发给客户端。 用户客户端&#xff1a;实现账号的注册、登…

【专题】数据库系统的基本原理

1. 数据库系统概述 1.1. 数据库系统的应用 电信业、银行业、金融业、销售业、联机的零售商、大学、航空业、人力资源、制造业等等。 1.2 数据库系统的概念 (1) 数据&#xff08;Data&#xff09; 数据是数据库存储的基本对象。是描述现实世界中各种具体事物或抽象概念的、可…

数据结构-5.1.树的定义和基本术语

一.树的基本概念&#xff1a; 1.根结点&#xff1a;最顶层的结点&#xff0c;有且仅有一个&#xff0c;没有前驱&#xff1b; 2.叶子结点&#xff1a;不能再有子结点&#xff0c;没有后继&#xff1b; 3.结点&#xff1a;用于存数据&#xff1b; 4.也有前驱和后继的说法&…

Spring Boot快速入门:HelloWorld示例

Spring Boot是一个非常流行&#xff0c;受欢迎的框架&#xff0c;它不仅常用于构建传统的单体式MVC应用程序&#xff0c;同时也非常适合用于搭建微服务架构。对于 Web 应用程序&#xff0c;Spring Boot 提供了用于创建 REST API、处理 HTTP 请求和使用 Thymeleaf 等模板引擎呈现…

介绍一下SAP 函数 NUMBER_GET_NEXT的妙用——获取SAP编码OBJECT

NUMBER_GET_NEXT 是 SAP 中用于获取下一个可用编号的函数模块&#xff0c;通常用于生成唯一的编号或序列号。这个函数模块的妙用在于它能够确保编号的唯一性和连续性&#xff0c;适用于需要生成订单号、发票号或其他业务对象编号的场景。 我在写ABAP程序时经常要调用这个函数来…

Oracle 数据库安装及配置

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

LSTM的变体

一、GRU 1、什么是GRU 门控循环单元&#xff08;GRU&#xff09;是一种循环神经网络&#xff08;RNN&#xff09;的变体&#xff0c;它通过引入门控机制来控制信息的流动&#xff0c;从而有效地解决了传统RNN中的梯度消失问题。GRU由Cho等人在2014年提出&#xff0c;它简化了…

45岁被裁员的程序员,何去何从?

在当今快速变化的技术行业&#xff0c;职业生涯的稳定性受到挑战。在45岁被裁员&#xff0c;对很多程序员来说&#xff0c;可能是一种惊慌失措的体验。然而&#xff0c;这个阶段也可以被视为一个重新审视和调整方向的机会。本文将对可能的出路进行全方位的分析&#xff0c;并提…

PHP泛目录生成源码,可生成长尾关键词页面,带使用方法视频教程

介绍&#xff1a; 真正的好东西&#xff0c;搞网站优化seo从业必备。可以快速提升网站权重&#xff0c;带来的流量哗哗的 PHP泛目录生成源码 可生成新闻页面和关键词页面 带使用方法视频教程 泛目录可以用来提升网站收录和排名 合理运用目录可以达到快速出词和出权重的效果…

[简单实践]Noisy Print - 自制基于加性噪声模型的简易降噪器

NoisyPrint 最近在学习的过程中&#xff0c;突然想起一个在Adobe Audition中用过的功能。 为什么会想到这个功能呢&#xff0c;因为在我使用DeepFilter的过程中&#xff0c;我发现对于一些低信噪比的信号来说&#xff0c;DeepFilter很容易出现过拟合现象&#xff0c;导致音源…

使用Git生成SSH密钥教程(附Git常用命令)

一、为什么使用SSH&#xff1f; 使用 Git 的 SSH&#xff08;安全外壳协议&#xff09;主要有以下几个原因&#xff1a;1. 安全性&#xff1a;SSH 是一种加密的网络协议&#xff0c;用于在网络中安全地运行网络服务。使用 SSH&#xff0c;所有传输的数据都会被加密&#xff0c…

Mysql高级篇(下)——数据库备份与恢复

Mysql高级篇&#xff08;下&#xff09;——数据库备份与恢复 一、物理备份与逻辑备份1、物理备份2、逻辑备份3、对比4、总结 二、mysqldump实现逻辑备份1、mysqldump 常用选项2、mysqldump 逻辑备份语法&#xff08;1&#xff09;备份一个数据库&#xff08;2&#xff09;备份…

微服务架构---认识Zuul

目录 认识Zuul简单的例子 第一个Zuul程序步骤1&#xff1a;创建父工程zuul-1步骤2&#xff1a;创建HystrixController类步骤3&#xff1a;搭建服务消费者eureka-consumer项目&#xff08;1&#xff09;创建一个config包&#xff0c;在config包下新建配置类RestConfig&#xff0…

HCIP-HarmonyOS Application Developer 习题(八)

&#xff08;填空&#xff09;1、声明式开发范式中使用装饰器( )装饰的结构体具有组件化能力&#xff0c;能够成为一个自定义组件。 答案&#xff1a;component 分析&#xff1a;component 装饰的struct表示该结构体具有组件化能力&#xff0c;能够成为一个独立的组件&#xff…

基于springboot的篮球竞赛预约平台

作者&#xff1a;计算机搬砖家 开发技术&#xff1a;SpringBoot、php、Python、小程序、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;Java精选实战项…

【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则

文章目录 C 继承详解&#xff1a;初阶理解与实战应用前言第一章&#xff1a;继承的基本概念与定义1.1 继承的概念1.2 继承的定义 第二章&#xff1a;继承中的访问权限2.1 基类成员在派生类中的访问权限2.2 基类与派生类对象的赋值转换2.2.1 派生类对象赋值给基类对象2.2.2 基类…

OkHttp

OkHttp是一个用于Android和Java应用的高效HTTP客户端库。它具有以下优点&#xff1a; 优点 高效连接池&#xff1a; 支持连接复用&#xff08;Connection Pooling&#xff09;减少延迟。有效管理HTTP/2多路复用。 透明压缩&#xff1a; 自动处理Gzip压缩&#xff0c;减少传输…

Label Studio 半自动化标注

引言 Label Studio ML 后端是一个 SDK,用于包装您的机器学习代码并将其转换为 Web 服务器。Web 服务器可以连接到正在运行的 Label Studio 实例,以自动执行标记任务。我们提供了一个示例模型库,您可以在自己的工作流程中使用这些模型,也可以根据需要进行扩展和自定义。 1…

dotnet7==windows ZIP方式安装和web demo和打包

下载ZIP Download .NET 7.0 (Linux, macOS, and Windows) 解压 创建项目 mkdir MyWebApp cd MyWebApp "C:\Users\90816\Downloads\dotnet-sdk-7.0.317-win-x64\dotnet.exe" new webapp -n MyWebApp 运行项目 "C:\Users\90816\Downloads\dotnet-sdk-7.0.317-…