前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >数据结构与算法之双指针

数据结构与算法之双指针

作者头像
java小杰要加油
发布于 2021-08-13 06:22:46
发布于 2021-08-13 06:22:46
1.4K00
代码可运行
举报
文章被收录于专栏:java小杰要加油java小杰要加油
运行总次数:0
代码可运行

双指针

  • 今天来通过5个力扣题来分享下数据结构与算法中的一个解题方法——双指针

26. 删除有序数组中的重复项

力扣地址:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/

举个例子,大概就是想这样,最后返回4,因为有4个不同的数字

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
    public int removeDuplicates(int[] nums) {
        // 当数组为0时,返回0
        if(nums.length==0){
          return 0;  
        }
         // 定义慢指针
         int last = 0;
         // 定义快指针
         int fast = 0;
         // 当快指针没有走到末尾的时候
            while(fast<nums.length){
              // 如果慢快指针指向的数值不等于慢指针指向的数值
             if(nums[fast] != nums[last]){
               // 慢指针向前移动一位
                 last++;
                 // 将慢指针指向的数值变成快指针指向的数值
                 nums[last] = nums[fast];
             }
             //快指针向前移动一位
               fast++;
            }  
         // 返回满指针+1 这个时候就是不重复数组的长度
         return last+1;
    }
}

这其中最主要的就是

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  // 当快指针没有走到末尾的时候
  while(fast<nums.length){
    // 如果慢快指针指向的数值不等于慢指针指向的数值
   if(nums[fast] != nums[last]){
     // 慢指针向前移动一位
       last++;
       // 将慢指针指向的数值变成快指针指向的数值
       nums[last] = nums[fast];
   }
   //快指针向前移动一位
     fast++;
  }  
  • 慢指针和快指针都是是从左边第一个元素开始走的
  • 慢指针确保的是,从左边第一个元素到满指针指向的元素,这些元素不重复

当快指针没有走到末尾的时候,快指针无论如何都要向前走。

  • 当快指针指向的数值与慢指针指向的相等的时候,这个时候就意着,数据开始重复,而我们慢指针确保的是不重复数据,那么,慢指针不动,让快指针继续向前走
  • 当快指针指向的数值与慢指针指向的不等的时候,这个时候就意着慢指针需要向前移动,慢指针向前移动一位后,需要把此时慢指针指向的数值变成刚才那个快指针指向的数值,因为我们慢指针确保的是从最左边开始是不重复数据

具体变化如下

27. 移除元素

力扣地址:https://leetcode-cn.com/problems/remove-element/

举个例子,大概是这样

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
    public int removeElement(int[] nums, int val) {
         if(nums.length == 0){
             return 0;
         }
        int slow =0;
        int fast =0;
         // 快指针不到末尾时
         while(fast<nums.length){
             //快指针不等于需要移除的数值时
             if(nums[fast] != val){
                 //将快指针指向的数值赋值给慢指针
                nums[slow] = nums[fast];
                //慢指针继续前移
                slow ++;
             }
             //快指针移动
             fast++;
         }
         
         return slow;
    }
}
  • 慢指针指向的数都是最终数组中的,是删除要删除的数据后的数组
  • 当我们快指针指向要删除的数据的时候,慢指针不动,快指针前移
  • 当我们快指针指向的不是要删除的数据的时候,将快指针指向的数值赋值给慢指针,然后慢指针向前移动一位,快指针前移

209. 长度最小的子数组

力扣地址:https://leetcode-cn.com/problems/minimum-size-subarray-sum/

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        if(nums.length == 0){
            return 0;
        }
        // 窗口左边界
        int left = 0;
        // 窗口右边界
        int right = 0;
        //总和
        int sum =0;
        // 默认滑动窗口长度
        int result = Integer.MAX_VALUE;
        // 当滑动窗口右边界没到末尾的时候
        while(right <nums.length ){
            // 计算滑动窗口内的总和
            sum = sum + nums[right];
            // 当这次的总和 >= 目标值
            while(sum >=target){
                // 更新滑动窗口的长度,用上次长度和这次的滑窗长度比,取最短的
                result = Math.min(result, right- left+1);
                // 更新总和,减去左边界的值
                sum = sum - nums[left];
                // 滑动窗口左边界向右移动,收缩滑动窗口
                left++;
            }
             // 滑动窗口右边界向右移动
            right++;
        }
        // 如果result没变的话,代表没有符合条件的子数组,返回0,否则返回result  
        return result == Integer.MAX_VALUE ? 0: result;
    }
}

流程如下,主要观察图中绿色的滑动窗口的变化

487. 最大连续1的个数 II

  • 力扣地址:https://leetcode-cn.com/problems/max-consecutive-ones-ii/
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
    public int findMaxConsecutiveOnes(int[] nums) {
        int left = 0;
        int right = 0;
        // 0的个数 最大为1
        int zeroCount = 0;
        int result =0;
        while(right <nums.length){
            if(nums[right] == 0){
                zeroCount++;
            }
            // 0的个数大于一时 
            while(zeroCount>1){
                // 当左指针指向的数值是0的时候,0的个数减一
                if(nums[left] == 0){
                    zeroCount--;
                 }
                 // 移动左指针
                 left++;
            }
            // 更新结果
            result =  Math.max(result, right-left+1);
            //右指针移动
            right++;
        }
        return result;
    }
}

流程如下,主要观察图中绿色的滑动窗口的变化

1004. 最大连续1的个数 III

  • 力扣地址:https://leetcode-cn.com/problems/max-consecutive-ones-iii/

这个题和上个题的唯一区别就是由一开始允许的1个0变成了K个0

代码变化也不大,就是由1变成了K,完整代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
    public int longestOnes(int[] nums, int k) {
        int left =0;
        int right =0;
        int zeroCount =0;
        int result =0;
        while(right<nums.length){
            if(nums[right] == 0){
               zeroCount++;
            }

            while(zeroCount >k){
                if(nums[left] ==0){
                    zeroCount--;
                }
                left++;
            }
            result = Math.max(result, right - left +1);
            right++;
        }
        return result;

    }
}

总结

双指针,就是定义两个指针在指定的数组/链表上游走,在做一些自定义的操作。

  • 如果要细分的话,双指针有左右指针快慢指针滑动窗口三种类型,一般时间复杂度为O(n),空间复杂度为O(1),这就是双指针的精妙之处
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-08-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 java小杰要加油 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【算法/学习】双指针
双指针(Two Pointers):指的是在遍历元素的过程中,不是使用单个指针进行访问,而是使用两个指针进行访问,从而达到相应的目的。如果两个指针方向相反,则称为「对撞指针」。如果两个指针方向相同,则称为「快慢指针」。如果两个指针分别属于不同的数组 / 链表,则称为「分离双指针」。
IsLand1314
2024/10/15
1220
【算法/学习】双指针
双指针技巧直接秒杀五道算法题
本文是一两年前发过的 一篇文章,当时没多少人看,现在由于账号迁移的原因公众号里都搜索不到了,我就重新加工了一下,并且添加了新内容,直接套双指针技巧秒杀 5 道算法题。
labuladong
2021/09/23
3090
数组双指针直接秒杀七道题目
所谓左右指针,就是两个指针相向而行或者相背而行;而所谓快慢指针,就是两个指针同向而行,一快一慢。
labuladong
2022/03/30
5330
数组双指针直接秒杀七道题目
名词解释-双指针算法
其实双指针算法,并不是一种具体的公式或者范式。而是一种思路。一种节省时间运算的思路。
zinyan.com
2023/07/14
2150
名词解释-双指针算法
算法笔记(一)
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
chuckQu
2022/08/19
6270
前端学数据结构与算法(十二):有趣的算法 - 多指针与滑动窗口
如果说如何用算法高效有趣的解决某些问题,那多指针和滑动算法绝对是算其中的佼佼者。这也是笔者最初接触算法时觉得最有意思的一点,因为解决的问题是熟悉的,但配方却完全不同,本章我们从一个简单的交集问题出发,一步步的认识到多指针及滑动窗口解决某些问题时的巧妙与高效,本章主要以解LeetCode里高频题为参考~
飞跃疯人院
2020/11/19
5960
七日算法先导(二)——双指针
其中这个最小元素为啥要初始化为nums[0],简单的来说我们是从左到右遍历数组的,nums[i]每次减minS,假设minS初始化为其他值,那么可能出现跳过第一个值或者初始值不在数组中的情况
秋名山码神
2022/12/13
1970
LeetCode通关:数组十七连,真是不简单
数组基本上是我们最熟悉的数据结构了,刚会写“Hello World”不久,接着就是“杨辉三角”之类的练习。
三分恶
2021/08/10
3960
双指针/滑动窗口/移动队列
Never stop learning, beacuse life never stops teaching. 不要停止学习, 因为人生总有东西可教 there is always more you don`t know. 无重复字符最长子串 双指针/滑动窗口/移动队列 无重复字符最长子串 package cn.com.codingce.aaclengthoflongestsubstring; import java.util.Arrays; import java.util.HashMap; impor
后端码匠
2021/08/20
4940
七十三、从三数之和探究双指针思想
双指针是一种解决问题的技巧或者思维方式,指在访问一个序列中的数据时使用两个指针进行扫描,两个指针可以是同向的,也可以是反向的。
润森
2022/08/17
8110
七十三、从三数之和探究双指针思想
一、基础数据结构
1、当移动<font style="color:rgb(233, 105, 0);background-color:rgb(248, 248, 248);">right</font>扩大窗口,即加入字符时,应该更新哪些数据?
阿东知识库1
2024/09/03
1750
一、基础数据结构
【算法题】从0培养算法思想——双指针篇
• 对撞指针从两端向中间移动。⼀个指针从最左端开始,另⼀个从最右端开始,然后逐渐往中间逼
小皮侠
2024/04/08
1300
【算法题】从0培养算法思想——双指针篇
九十六、双指针和滑动窗口算法模板
在四种二分变种中,根据王争算法专栏中,写死low = 0,high = len(list) - 1。循环条件low <= high。往左移动high = mid - 1,往右移动low = mid + 1
润森
2022/08/18
2450
九十六、双指针和滑动窗口算法模板
【双指针算法】——还不会双指针?看这里一篇就能让你明白其中的奥妙
https://leetcode.cn/problems/move-zeroes/
用户11286421
2024/10/11
4090
【双指针算法】——还不会双指针?看这里一篇就能让你明白其中的奥妙
leetcode 双指针算法专题
双指针是一种方法,一种思想一种技巧,也谈不上什么特别的算法,在二分查找中经常使用这个技巧,具体就是用两个变量动态的存储两个或者多个的结点,来方便我们进行一些操作,通常使用在线性结构中,比如说数组或者是链表。 在我们遇到像数组,链表这类数据结构的算法题目的时候,应该要想得到双指针的来解决问题。特别是链表类的题目,经常需要用到两个或多个指针配合来记忆链表上的节点,完成某些操作。链表这种数据结构也是树形结构和图的原型,所以有时候在关于图和树形结构的算法题目中也会用到双指针。
Albert_xiong
2021/06/21
5510
leetcode 双指针算法专题
什么时候可以用双指针,该咋用?
双指针是我们做题中经常用到的思想,所以这个思想在刷题初期是一定要会的。其实我们早就学习过这个方法,那就是我们在学习数据结构的二分查找,下面我们通过二分查找来描述一下这个思想。
灵魂画师牧码
2020/11/06
1.1K0
什么时候可以用双指针,该咋用?
写给前端的算法进阶指南,我是如何两个月零基础刷200题
最近国内大厂面试中,出现 LeetCode 真题考察的频率越来越高了。我也观察到有越来越多的前端同学开始关注算法这个话题。
前端迷
2020/07/22
9250
写给前端的算法进阶指南,我是如何两个月零基础刷200题
力扣刷题(数组篇)
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 (leetcode-cn.com)  小王的主页:(14条消息) 学好c语言的小王同学的博客_CSDN博客-领域博主 小王的gitee:比特王信哲 (bitewang) - Gitee.com
王同学要努力
2022/12/20
2250
力扣刷题(数组篇)
前端leetcde算法面试套路之双指针
上一 part 刚写完二分和滑窗,他们都属于特殊的双指针方法,所以这一 part 直接汇总一下除了特殊的二分和滑窗外的其他双指针写法
js2030code
2022/11/02
4830
LeetCode分类刷题:双指针(Two Pointers)
双指针(Two Pointers)一直是程序员面试中的一个必须准备的主题, 面试中双指针出现的次数比较多,主要由于在工作中指针经常用到,指针问题能够直接反应面试者的基础知识、代码能力和思维逻辑,因此双指针的问题必须掌握。
ACM算法日常
2019/03/06
2K0
相关推荐
【算法/学习】双指针
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验