减治法

简介: 分治法是把一个大问题划分为若干个子问题,分别求解各个子问题,然后再把子问题的解进行合并得到原问题的解。减治法同样是把一个大问题划分为若干个子问题,但是这些子问题不需要分别求解,只需求解其中的一个子问题,因而也无需对子问题的解进行合并。

分治法和减治法的区别。

分治法是把一个大问题划分为若干个子问题,分别求解各个子问题,然后再把子问题的解进行合并得到原问题的解。

减治法同样是把一个大问题划分为若干个子问题,但是这些子问题不需要分别求解,只需求解其中的一个子问题,因而也无需对子问题的解进行合并。

所以,严格的说,减治法应该是一种退化了的分治法,时间复杂性一般是O(log2 n)。

减治法在将原问题分解为若干个子问题后,利用了规模为n的原问题的解与较小规模(通常是n/2)的子问题的解之间的关系,这种关系通常表现为:

(1)原问题的解只存在于其中一个较小规模的子问题中;

(2)原问题的解与其中一个较小规模的解之间存在某种对应关系

查找问题中的减治法

折半查找

折半查找利用了记录按关键码有序的特点,其基本思想为:在有序表中,取中间记录作为比较对象,若给定值与中间记录的关键码相等,则查找成功;若给定值小于中间记录的关键码,则在中间记录的左半区继续查找;若给定值大于中间记录的关键码,则在中间记录的右半区继续查找。不断重复上述过程,直到查找成功,或所查找的区域无记录,查找失败。

  1. 剑指 Offer 53 - II. 0~n-1中缺失的数字 - 简单 代码
  2. 668. 乘法表中第k小的数 - 困难 代码

二叉查找树

二叉查找树又称二叉排序树,是具有以下性质的二叉树;

(1)若它的左子树不空,则左子树上所有节点的值均小于根节点的值

(2)若它的右子树不空,则右子树上所有节点的值均大于根节点的值

(3)它的左右子树也都是二叉排序树

在二叉排序树root中查找给定值k的过程是:

(1)若root是空树,则查找失败

(2)若k=根节点的值,则查找成功

(3)否则,若k<根节点的值,则在root的左子树上查找

(4)否则,在root的右子树上查找

讲这个感觉没啥用,二叉查找树比较麻烦的是如何构建这颗树吧。而且其实折半查找就是用数组表示了二叉查找树结构。这个就不找题做了,没想到有什么场景。

排序问题中的减治法

堆排序

定义:堆(heap)是具有下列性质的完全二叉树:每个节点的值都小于或等于其左右孩子节点的值(小根堆);或者每个节点的值都大于或等于其左右孩子节点的值(大根堆)。如果将具有个节点的堆按层序从1开始编号,则节点之间满足如下关系:

(1)ki <= k(2i) 且 ki <= k(2i+1)

(2)ki >= k(2i) 且 ki >= k(2i+1)

1<=i<=n/2

这个定义其实说明了用数组存储堆的话,数据的特征。


堆排序是利用堆的特性进行排序的方法,其基本思想是:首先将待排序的记录序列构造成一个堆,此时,选出了堆中所有记录的最大者即堆顶记录,然后将它从堆中移走,并将剩余的记录再调整成堆,这样又找出了次大的记录,以此类推,直到堆中只有一个记录为止。


堆调整问题是关键,主要有筛选调整法和插入法调整。

筛选法调整堆要解决的关键问题是:在一个完全二叉树中,根节点的左右子树均是堆,如何调整根节点,使整个完全二叉树成为一个堆?

方法为:根节点和左右子树的根节点比较,将最大值和和根节点进行交换,直到所有子树均为堆或者调整的节点到了叶子节点。

插入法调整堆要解决的问题是:在堆中插入一个节点,如何调整被插入的节点,使整个完全二叉树仍然是一个堆?

方法为:在末尾插入节点,将该节点与双亲节点进行比较,如果不满足堆条件,将该节点和根节点进行交换,重复执行这个过程,直到节点小于双亲节点或者到了根节点。

堆排序需要完成两个操作:

1)将数组调整为堆:

  • 方法1:从最后一个非叶子节点开始,比较该节点和子节点的值进行调整,调整完成后,比较倒数第二个非叶子节点,持续这个过程,直到根节点。第一个叶子节点,一定是序列长度/2,所以第一个非叶子节点的索引就是arr.length / 2 -1。参考
  • 方法2:使用插入法,按照数组顺序,一个一个插入

2)排序:将根节点和最后一个叶子节点对调,然后使用筛选法将剩余的元素重新构建成堆

  1. 面试题 17.14. 最小K个数 - 中等 代码

选择问题

设无序序列T=(r1,r2,……,rn),T的第k(1<=k<=n)小元素定义为T按升序排列后在第k个位置上的元素。给定一个序列T和一个整数k,寻找T的第k小元素的问题称为选择问题。特别地,将寻找第n/2小元素的问题称为中值问题。

这种类型的题可以借鉴快速排序的划分过程。每次划分,会确定出一个轴值,判断轴值所在位置比k大还是小,从而减小范围。使用这种方案时间复杂度为O(n)。


这种类型的题和上面最小K个数的区别在于,一个选择出一个数值,一个需要返回一定范围。

  1. 215. 数组中的第K个最大元素 - 中等 代码

组合问题中的减治法

淘汰赛冠军问题

假设有n=2^k个选手进行经济淘汰赛,最后决出冠军的选手,用函数bool Comp(string mem1, string mem2)

模拟两位选手的比赛,若mem1获胜则函数Comp返回TRUE,否则函数Comp返回FALSE,并假定可以在常数时间内完成函数Comp的执行,如何模拟淘汰比赛过程?要求时间复杂度为O(n)。

这个思路比较简单,将所有用户二等分,两段的起始索引为0和n/2,让0与n/2比较,赢的放前面。一直遍历到n/2-1,前n/2都是胜利的人。再次二等分,做这种循环,最终第0个人是最终胜利者。

这种问题很难找到对应的练习题,因为这种题有个特性,就是两个数据只能存活一个。而且这道题编写也不是很困难,就不做了,但是大家如果有合适的题可以提供给我。

假币问题

在n枚外观相同的硬币中,有一枚是假币,并且已知假币教轻。可以通过一架没有刻度的天平来任意比较两组硬币,从而得知两组硬币的重量是否相同,或者哪一组更轻一些,但不知道轻多少,假币问题是要求设计一个搞笑的算法来检测出这枚假币。

因为知道哪个假币教轻,所以计算思路比较简单

方案1:分成两堆,进行比较,教轻的一堆再分成两堆,直至找到最轻的硬币,时间复杂度为O(log2 n)

方案2:分成三堆,如果比较两堆重量一样,则第三堆有假币;如果比较的两堆有一堆教轻,则该堆有假币。重复这个过程,直至找到最轻的硬币,时间复杂度为O(log3 n)

现在让我们把问题复杂化,如果有8枚硬币(a b c d e f g h),假币重量教轻还是较重,如何处理?

解决这个问题需要使用判定树,具体细节留给大家自己思考。

假币问题乐扣上也没有找到相应的题目,毕竟有值但是又不让用的题比较难出,大家也比较难接受,不过在实际生活中,这个还是很有用的。

总结

减治法和分治法是相似的,只不过减治法每次执行规模会减半。本篇里需要重点关注的有

查找问题:折半查找

排序问题:堆排序、选择问题

其中折半查找大家可能都觉得很容易,其实只是思想理解起来容易,真正编码的时候,涉及到很多边界条件,我用折半查找面试过很多人,能写的完美的比较少。

堆排序是必然要掌握的,关于堆的相关习题太多,大家一定要自己做一番。

最后

大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

往期文章回顾:

算法

  1. 算法学习计划
  2. 蛮力法
  3. 分治法
  4. 减治法

技术

  1. 浅谈微服务
  2. TCP性能优化
  3. 限流实现1
  4. Redis实现分布式锁
  5. Golang源码BUG追查
  6. 事务原子性、一致性、持久性的实现原理
  7. CDN请求过程详解
  8. 记博客服务被压垮的历程
  9. 常用缓存技巧
  10. 如何高效对接第三方支付
  11. Gin框架简洁版
  12. InnoDB锁与事务简析

读书笔记

  1. 敏捷革命
  2. 如何锻炼自己的记忆力
  3. 简单的逻辑学-读后感
  4. 热风-读后感
  5. 论语-读后感

思考

  1. 对项目管理的一些看法
  2. 对产品经理的一些思考
  3. 关于程序员职业发展的思考
  4. 关于代码review的思考
  5. Markdown编辑器推荐-typora
相关文章
|
前端开发
UniApp 中的 image 属性讲解
UniApp 中的 image 属性讲解
1262 2
|
小程序 搜索推荐
uniapp中如何使用image图片
uniapp中如何使用image图片
2310 0
|
存储 数据采集 运维
阿里巴巴DevOps实践指南(二十四)| 智能运维
智能运维( AIOps )是依托于阿里巴巴 DevOps 经验沉淀而来的智能化运维平台,通过运维大数据的积累,以及算法团队多种算法的校对,我们将运维提升到新的高度,通过 AI 来帮我们查看数据、判断异常、决策运维操作,形成监、管、控一体化的运维平台。
阿里巴巴DevOps实践指南(二十四)| 智能运维
|
存储 Java 数据库连接
【Mybatis】关系映射 表对象之间的关系
【Mybatis】关系映射 表对象之间的关系
297 0
|
6月前
|
API 开发者
HarmonyOS 之 @Require 装饰器自学指南
在 HarmonyOS 应用开发中,组件初始化传参校验是常见难题。本文深入探讨了 `@Require` 装饰器的使用方法,它能在编译阶段严格校验组件构造传参,提升代码健壮性与开发效率。文章涵盖装饰器定义、版本支持、限制条件及典型使用场景(如父子组件传参校验和 `@ComponentV2` 初始化),并通过错误示例分析常见问题。总结中强调了 `@Require` 的重要性,助力开发者编写更稳定高效的代码。适合鸿蒙开发者学习参考!
169 28
HarmonyOS 之 @Require 装饰器自学指南
|
9月前
|
弹性计算 网络协议 安全
下一代互联网IPv6规模部署和应用
本文介绍了IPv6在云计算场景下的规模部署与应用创新,强调其作为互联网演进的必然趋势及网络强国建设的基础支撑作用。文章从企业上云部署IPv6、云上IPv6网络底座构建、双栈方案全景图、专有云IPv6改造、政务云和金融客户的实践案例等方面展开讨论,详细阐述了IPv6在不同场景下的技术要求和服务能力。最后展望了IPv6与AI结合的未来发展方向,旨在推动IPv6的全面应用和技术创新。
|
缓存 负载均衡 数据管理
深入探索微服务架构的核心要素与实践策略在当今软件开发领域,微服务架构以其独特的优势和灵活性,已成为众多企业和开发者的首选。本文将深入探讨微服务架构的核心要素,包括服务拆分、通信机制、数据管理等,并结合实际案例分析其在不同场景下的应用策略,旨在为读者提供一套全面、深入的微服务架构实践指南。**
**微服务架构作为软件开发领域的热门话题,正引领着一场技术革新。本文从微服务架构的核心要素出发,详细阐述了服务拆分的原则与方法、通信机制的选择与优化、数据管理的策略与挑战等内容。同时,结合具体案例,分析了微服务架构在不同场景下的应用策略,为读者提供了实用的指导和建议。
|
弹性计算
阿里云服务器多少钱一年?2024年5月云服务器价格表曝光!
2024年5月,阿里云服务器价格曝光,ECS云服务器2核2G3M带宽低至99元/年,2核4G5M优惠价199元/年。香港轻量服务器24元/月,4核8G服务器700元/年。其他配置如8核32G也有不同优惠。详细价格表及活动信息见阿里云服务器ECS页面
520 6
|
SpringCloudAlibaba 监控 Java
SpringCloud Alibaba微服务-- Sentinel的使用(保姆级)
SpringCloud Alibaba微服务-- Sentinel的使用(保姆级)
|
负载均衡 前端开发 Java