什么样的问题适合用双指针技巧?当问题是从一个有序的数组或链表中,找到一个元素的子集,该子集需要满足某种限制。 这时候就特别适合用双指针。这个子集可能是某两个元素,某三个元素,甚至是一个子数组。

1 举个栗子

给你一个升序排列的数组和一个目标值,从该数组中找出两个元素,使它们的和等于目标值

看到这个问题,你会不会觉得:

这不就是两层for循环嘛。你轻松写下了如下代码:

def twoSum(nums: List[int], target: int) -> List[int]:for i in range(len(nums)):for j in range(i+1, len(nums)):if nums[i] + nums[j] == target:return [i, j]

这个解法,问题在于时间复杂度是。在实际中有点难以接受。这个时候就可以用上我们的双指针技巧。

在滑动窗口技巧中,我曾经反复强调,滑动窗口不过是对暴力搜索算法的优化。 同理,双指针技巧也是这样的。网上很多讲双指针技巧的,我还没有看到谁从这个角度来讲的,如果有麻烦加微信(milter007)告诉我。而我认为只有从这个角度来讲,才能减少认知的跳跃,更容易理解双指针的本质所在。

2 问题分析

分析上面的暴力算法,我们看到外层循环的目的,是一个一个元素看,尽量找到和该元素之和等于目标值的元素。这个过程是不可能省略的,因为省略就意味着没有查找全面彻底。

但是,内层循环是可以进行优化的。并不需要那么傻乎乎地一个一个查找。举例来说,如图所示:

Pointer1就代表上面的外层循环中的,Pointer2就代表上面的内层循环中的。只不过内层循环是从数组尾部开始而已。目标值是6。

我们看到,此时 ,于是,我们的Pointer2代表的内层循环就会往前走,如图所示:

此时,,此时,Pointer2代表的内层循环没必要继续了,因为数组是升序排列的,越往前,元素值越小,和Pointer1的和自然越小。所以,内层循环可以提前退出,这就是我们的第一个优化点。

根据上面的暴力算法,内层循环退出后,如果没有找到答案,外层循环就要继续,这就是Pointer1要向前走。Pointer1向前走一步如下所示:

我们这个例子中恰好找到答案了。但假如此时没有找到答案呢?比如这种情况:

向前移动Pointer1之后, ,这个时候,我们该怎么办呢?需要按照暴力搜索的逻辑,重启内层循环,从数组尾部开始,一个一个和此时的Pointer1(也就是2)进行匹配吗?

答案是不需要。

因为此时,我们已经可以断定,整个数组中是不可能有哪个数与2的和等于6的,为什么呢?因为 3.5 往右的每一个数,它们与1的和都是大于6的,自然与2的和更是大于6。

为什么3.5 往右的每一个数,它们与1的和都是大于6的?因为这是上一轮循环的结果,我们的Pointer2是从尾部一个一个往前推,如果与1的和大于6,就继续,直到小于6才停下来的。

而3.5往左的每一个数,都比3.5还小,它们与2的和只能比6更小。

既然这样,我们就压根不用进行任何内层循环查找了,直接将外层循环推进一步,就是将Pointer1向右推一步,这就是我们的第二个优化点。

细心的你,一定想问,如果是这种情况呢:

此时, ,那我们就需要进行内层循环了,不过,我们只用从现在的Pointer2的位置继续向数组头部方向进行查找就是,而不用从数组尾部重新开始这就是我们的第三个优化点。

上面,其实就是双指针算法了!表面上看起来,两个指针,一会儿P2向数组头部走,一会儿P1向数组尾部走,看不出章法,第一次学习的同学,可能感到一头雾水。通过咱们的分析,原来就是对暴力查找算法的一个优化而已。 是不是顿时觉得清爽很多了?

3 代码实现

def pair_with_targetsum(arr, target_sum):left, right = 0, len(arr) - 1while(left < right):current_sum = arr[left] + arr[right]if current_sum == target_sum:return [left, right]if target_sum > current_sum:left += 1  # 移动Pointer1else:right -= 1  # 移动Pointer2
return [-1, -1]

双指针问题最简单的教程(1)相关推荐

  1. vim简单使用教程【转】

    vim的学习曲线相当的大(参看各种文本编辑器的学习曲线),所以,如果你一开始看到的是一大堆VIM的命令分类,你一定会对这个编辑器失去兴趣的.下面的文章翻译自<Learn Vim Progress ...

  2. java map set_java中Map、Set、List的简单使用教程(快速入门)

    Map.Set.List List的常用方法 1.创建 List list = new ArrayList<>(); List list = new LinkedList<>( ...

  3. 【转】正则表达式简介及在C++11中的简单使用教程

    [转]正则表达式简介及在C++11中的简单使用教程 正则表达式Regex(regular expression)是一种强大的描述字符序列的工具.在许多语言中都存在着正则表达式,C++11中也将正则表达 ...

  4. PHP在WPS中的应用,PHP+Laravel的简单应用教程【ajax的使用】,wps的使用教程

    PHP+Laravel的简单应用教程[ajax的使用]PHP·拉弗尔的简单应用教程[阿贾克斯的使用],下面由Laravel框架教程栏目给大家介绍PHP Laravel的简单应用教程[阿贾克斯的使用], ...

  5. 史上最简单MySQL教程详解(进阶篇)之存储过程(一)

    史上最简单MySQL教程详解(进阶篇)之存储过程(一) 史上最简单MySQL教程详解(进阶篇)之存储过程(一) 什么是存储过程 存储过程的作用 如何使用存储过程 创建存储过程 DELIMITER改变分 ...

  6. 史上最简单MySQL教程详解(进阶篇)之存储引擎介绍及默认引擎设置

    什么是存储引擎? MySQL存储引擎种类 MyISAM 引擎 InnoDB引擎 存储引擎操作 查看存储引擎 存储引擎的变更 修改默认引擎 什么是存储引擎? 与其他数据库例如Oracle 和SQL Se ...

  7. IDEA简单配置教程

    IDEA简单配置教程 --做好前期配置工作,后期少走弯路. 创建模块(Module) 设置(Settings) 设置主题 窗体及菜单字体及大小 设置编辑区主题 通过插件(plugins)更换主题 设置 ...

  8. kindle的xray怎么用_Xray简单使用教程

    Xray简单使用教程 0X00下载 xray 为单文件二进制文件,无依赖,也无需安装,下载后直接使用. 下载地址为: 注意: 不要直接 clone 仓库,xray 并不开源,仓库内不含源代码,直接下载 ...

  9. navicat fo mysql 教程_Navicat For MySQL的简单使用教程

    1.前提是必须先安装好MySQL数据库(Mac下安装MySQL数据库见前一篇) 2.安装Navicat 3.点击navicate左上角:连接->MySQL->先测链接下,如果提示连接成功, ...

最新文章

  1. 极限学习机的matlab程序_新程序员七宗罪,新手别踩雷
  2. 信息安全系统设计基础期末总结
  3. 刷脸背后,卷积神经网络的数学原理原来是这样的
  4. 串口通信模块1:串口基础知识
  5. 5种较为简单的缺失值处理方法
  6. SAP SD数据库表一览
  7. 基于Flink CDC打通数据实时入湖
  8. python调用bing翻译API V2
  9. opencv cvtcolor函数中断异常
  10. DiskPart使用方法(ZT)
  11. css中滑轮中是如何做的,横向的网页如何实现鼠标滑轮横向移动?_html/css_WEB-ITnose...
  12. WINCE下模拟鼠标点击,移动
  13. 秋从饶合似陶家,遍绕篱边日渐斜。不是花中偏爱菊,此花开尽更无花
  14. Oracle OCP(05):转换函数
  15. 【环境搭建】Ubuntu安装vulkan
  16. 3dmax入门到精通
  17. Py正则表达式学习笔记:特殊字符——中括号表达式、限定符表达式
  18. 第十四届蓝桥杯(Web 应用开发)模拟赛 1 期-职业院校组-知识点题解
  19. pcl启动java代码_我的世界PCL启动器-Plain Craft Launcher(PCL启动器)下载 v1.0.9免费版--pc6下载站...
  20. 甲骨文或收购市值775亿美元的埃森哲

热门文章

  1. [POJ3261] Milk Patterns
  2. springboot 学习笔记(三)
  3. 软件工程网络15结对编程作业
  4. react遇到的各种坑
  5. 如何将github上的 lib fork之后通过podfile 改变更新源到自己fork的地址
  6. 使用PowerShell登陆多台Windows,测试DCAgent方法
  7. 安卓学习-界面-ui-ListView
  8. 《ASP.NET MVC4 WEB编程》学习笔记------Web API 续
  9. EasyPHP-2.0b1+ Mantis-1.1.0安装及技巧
  10. 一份来自山东院校的考研调剂系统已开放名单!