双指针算法是一种比较常用于搜索链表或数组相关的问题,很多算法的基本的解题思路就是使用暴力搜索法。而双指针是对暴力搜索的一种优化,通过双指针可以减少数据的遍历次数。通常双指针是有两个指针,叫做 light 左指针和 right 右指针,或者叫做快指针和慢指针

  • 作为左右指针的话,一般是在数组的或者链表的头尾两侧,从两遍往中间收缩,获取到符合条件的答案。
  • 作为快慢指针的话,主要应用于解决链表问题。通常快指针移动的比慢指针移动的快,这种方法可以用来检测链表中是否有环、寻找链表的中间结点。

LeetCode 题解

11.盛最多水的容器

题目描述

解题思路

这题可以暴力破解法,双循环遍历出来,查出所有存在的情况,但是时间复杂是O(N²),实现简单,但是比较耗时。而且本题也无需遍历所有的情况,分析一下解题思路:

本题求解的是最大的盛水面积,盛水面积是由宽和高组成,也就是找到横坐标的长度 * 两条竖线中更端的线的乘积。

最开始时候,左右指针分别指向数组的左右两端,获取到容量 min(1,7) * 8。

然后两遍指针往中间收缩,需要往中间移动一个指针,重点是需要移动哪一个?往中间收缩,宽度一定是变短,而高度是由两条竖线中的最短的一条决定。移动更大竖线的指针,面积肯定会减少,因为宽度和高度都在减少,所以需要移动竖线更小的指针,面积才可能增加。上面移动左边的竖线。面积由原来的 min(1,7) * 8 = 8 到 min (8,7) * 7 = 49,面积增多了。

使用 max 变量记录当前最大的面积,和每次搜索的面积做对比,获取到最大值。代码如下所示:

class Solution {
public int maxArea(int[] height) {
int left = 0;
int right = height.length -1;
int max = 0;
while (left < right) {
int capacity = Math.min(height[left],height[right]) * (right - left);
if (max < capacity) { max = capacity;}
if(height[left] < height[right]) {
left++;
}else{
right--;
} }
return max;
}
}

15.三数之和

题目描述

解题思路 for + 双指针

无论是两数之和或者三数之和都可以使用到双指针,但是双指针只有两个指针无法同时记录三个数,所以就需要使用一个 for 循环,for 每次遍历记录一个值,再使用双指针记录左右两个值。

为了减少遍历的次数,需要对数组做一个排序。然后 for 循环定位到第一个元素,左右两个指针的目标值就是 target - for 循环定位元素。左右指针相加得到总和 sum。

  • 如果sum < target,左指针往右移动。
  • 如果sum > target,右指针往左移动。
  • 如果sum = target,符合条件,返回值。

然后定位到第二个元素,继续使用双指针收缩遍历。

代码如下:

class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> lists = new ArrayList<>();
Arrays.sort(nums);
//for循环 + 双指针
for (int i = 0; i < nums.length; i++) {
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
int target = -nums[i];
int left = i +1,right = nums.length - 1;
while (left < right) {
int sum = nums[left] + nums[right];
if (sum == target) {
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[left]);
list.add(nums[right]);
lists.add(list);
break;
} else if (sum < target) {
left++;
} else {
right--;
}
}
}
return lists;
}
}

142. 环形链表 II

题目描述

解决方案

这道题在链表那篇文章也有,求解使用了 hash 表,遍历链表,存储在 hash 表中。如果有相同的数据,说明链表是有环了。本题采用快慢指针的办法。

起始的时候,快慢指针都在首节点。

慢指针一次走一步,快指针一次走两步,移动第一次之后。

fast 指针走过链表末端,说明链表无环,此时直接返回 null。如果两个指针遇上,说明链表有环,当两个指针第一次相遇时,fast 走的步数是 slow 的两倍。

从相遇点到入环点的距离加上 n−1 圈的环长,恰好等于从链表头部到入环点的距离。当 slow 和 fast 相遇时,可以在使用一个额外的指针 ptr,开始指向链表头部,随后它和 slow 每次往后移动,最后他们会在入环结点相遇,此时就能获取到入环结点

public class Solution {
public ListNode detectCycle(ListNode head) {
if (head == null) {
return null;
}
ListNode slow = head, fast = head;
while (fast != null) {
slow = slow.next;
if (fast.next != null) {
fast = fast.next.next;
} else {
return null;
}
if (fast == slow) {
ListNode ptr = head;
while (ptr != slow) {
ptr = ptr.next;
slow = slow.next;
}
return ptr;
}
}
return null;
}
}

总结

双指针算法是一种常用于解决数组或链表相关问题的算法技巧。该算法通常涉及到使用两个指针(索引),它们可以从数组或链表的不同位置出发,根据问题的要求,以一定的方式移动这些指针,从而在数组或链表上执行一些特定的操作。一般使用左右指针和快慢指针两种方式。

图解 LeetCode 算法汇总——双指针的更多相关文章

  1. LeetCode算法题目解答汇总(转自四火的唠叨)

    LeetCode算法题目解答汇总 本文转自<四火的唠叨> 只要不是特别忙或者特别不方便,最近一直保持着每天做几道算法题的规律,到后来随着难度的增加,每天做的题目越来越少.我的初衷就是练习, ...

  2. LeetCode算法题-Degree of an Array(Java实现)

    这是悦乐书的第294次更新,第312篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第162题(顺位题号是697).给定一个由正整数组成的非空数组,该数组的度数被定义为任意 ...

  3. LeetCode算法题-Valid Palindrome II(Java实现)

    这是悦乐书的第287次更新,第304篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第155题(顺位题号是680).给定非空字符串s,最多可以删除一个字符. 判断它是否是回 ...

  4. LeetCode算法题-Two Sum IV - Input is a BST(Java实现)

    这是悦乐书的第280次更新,第296篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第148题(顺位题号是653).给定二进制搜索树和目标数,如果BST中存在两个元素,使得 ...

  5. LeetCode算法题-Sum of Square Numbers(Java实现)

    这是悦乐书的第276次更新,第292篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第144题(顺位题号是633).给定一个非负整数c,判断是否存在两个整数a和b,使得a的 ...

  6. LeetCode算法题-K-diff Pairs in an Array(Java实现)

    这是悦乐书的第254次更新,第267篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第121题(顺位题号是532).给定一个整数数组和一个整数k,您需要找到数组中唯一的k- ...

  7. LeetCode算法扫题系列19

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9104677.html LeetCode算法第19题(难度:中等) 题目:给定一个链表,删 ...

  8. LeetCode算法题-Find All Anagrams in a String(Java实现)

    这是悦乐书的第228次更新,第240篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第95题(顺位题号是438).给定一个字符串s和一个非空字符串p,找到s中p的字谜的所有 ...

  9. LeetCode算法题-Fizz Buzz(Java实现)

    这是悦乐书的第221次更新,第233篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第88题(顺位题号是412). 编写一个程序,输出从1到n的数字的字符串表示.但对于三的 ...

  10. LeetCode算法题-Intersection of Two Arrays II(Java实现)

    这是悦乐书的第208次更新,第220篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第76题(顺位题号是350).给定两个数组,编写一个函数来计算它们的交集.例如: 输入: ...

随机推荐

  1. 现代 C++ 性能飞跃之:移动语义

    *以下内容为本人的学习笔记,如需要转载,请声明原文链接微信公众号「ENG八戒」https://mp.weixin.qq.com/s/Xd_FwT8E8Yx9Vnb64h6C8w 带给现代 C++ 性能 ...

  2. 曲线艺术编程 coding curves 第十章 螺旋曲线(SPIRALS)

    原作:Keith Peters https://www.bit-101.com/blog/2022/11/coding-curves/ 译者:池中物王二狗(sheldon) 源码:github: ht ...

  3. Java发展历程及各版本新特性

    Java的历史是非常有意思的.1990年底,Sun Microsystems在工作站计算机市场上领先世界,并继续保持健康发展.Sun想把本公司的创新和专业知识应用到即将到来的消费电子市场领域,于是该公 ...

  4. 【python基础】类-类属性

    在初始类中,我们介绍了如何访问类属性,除了访问类属性外还有其他操作类属性的情况,我们将在这里做详细介绍: 1.给类属性指定默认值 类中的每个属性都必须有初始值,哪怕这个值是0或者空字符串.在有些情况下 ...

  5. linux 服务器上如何判断网络是否开通

      项目上由于升级了kafka需要测试下网络是否是通的,因此需要使用命令 nc -zv ip地址 端口这个命令来跑一下网络是否是通的,最后发现是新的kafka的config使用了新的端口,没有开通网络 ...

  6. 如何使用libavcodec将.h264码流文件解码为.yuv图像序列?

    一.打开和关闭输入文件和输出文件 //io_data.cpp static FILE* input_file= nullptr; static FILE* output_file= nullptr; ...

  7. Redis缓存同步1-策略介绍

    缓存数据同步策略示意图 在大多数情况下,我们通过浏览器查询到的数据都是缓存数据,如果缓存数据与数据库的数据存在较大差异的话,可能会产生比较严重的后果的.所以,我们应该也必须保证数据库数据.缓存数据的一 ...

  8. 使用LabVIEW实现 DeepLabv3+ 语义分割含源码

    前言 图像分割可以分为两类:语义分割(Semantic Segmentation)和实例分割(Instance Segmentation),前面已经给大家介绍过两者的区别,并就如何在labview上实 ...

  9. 2023-07-19:布尔表达式 是计算结果不是 true 就是 false 的表达式 有效的表达式需遵循以下约定: ‘t‘,运算结果为 true ‘f‘,运算结果为 false ‘!(subExpr

    2023-07-19:布尔表达式 是计算结果不是 true 就是 false 的表达式 有效的表达式需遵循以下约定: 't',运算结果为 true 'f',运算结果为 false '!(subExpr ...

  10. SpringBoot项目:net.sf.jsqlparser.parser.ParseException: Encountered unexpected token:XXXXX

    原文地址 写在前面 最近开发过程中,在where条件中使用IF函数,在MySQL数据库中,使用Navicat运行没有问题,但是运行项目的时候,死活过不去,一直报错,后来一番折腾找到了解决方案,所以,以 ...