目录

  • 快慢指针
    • 1 判定链表中是否含有环
    • 2 已知链表中含有环,返回这个环的起始位置
    • 3 寻找链表的中点
    • 4 寻找链表的倒数第n个元素
  • 左右指针
    • 1 二分查找
    • 2 两数之和 -- 有序数组
    • 3 反转数组
    • 4 滑动窗口算法

链接

双指针技巧再分为两类,一类是「快慢指针」,一类是「左右指针」。
者解决主要解决链表中的问题,比如典型的判定链表中是否包含环;
者主要解决数组(或者字符串)中的问题,比如二分查找。

快慢指针

1 判定链表中是否含有环

力扣第 141 题

class Solution {public:bool hasCycle(ListNode* head) {if (head == nullptr || head->next == nullptr) {return false;}ListNode* slow = head;ListNode* fast = head->next;while (slow != fast) {if (fast == nullptr || fast->next == nullptr) {return false;}slow = slow->next;fast = fast->next->next;}return true;}
};

2 已知链表中含有环,返回这个环的起始位置

相遇点到环起点 的 步数链头部 到 环起点的步数相同(前提是 slow 单步,fast 两步)

ListNode detectCycle(ListNode head) {ListNode fast, slow;fast = slow = head;while (fast != NULL&& fast.next != NULL) {fast = fast.next.next;slow = slow.next;if (fast == slow) break;} // 上面的代码类似 hasCycle 函数slow = head;while (slow != fast) {fast = fast.next;slow = slow.next;}return slow;
}

3 寻找链表的中点

当链表的长度是奇数时,slow恰巧停在中点位置;
如果长度是偶数,slow最终的位置是中间偏右

通过判断 快指针fast->next是否为NULL 来看链表长度是偶数还是奇数;
为NULL是偶数,不为NULL为奇数

力扣第 876 题

class Solution {public:ListNode* middleNode(ListNode* head) {ListNode *slow ,*fast;slow=fast=head;while (fast != NULL && fast->next != NULL) {slow = slow->next;fast = fast->next->next;}return slow;}
};

4 寻找链表的倒数第n个元素

力扣第 19 题

class Solution {public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode *slow,*fast;fast=slow=head;while(n-- > 0)fast=fast->next;if(fast==nullptr) return head->next; // 此时fast指向尾部,第n个即首部// fast 指向 首部时,fast不为null fast->next 为空while(fast!=nullptr&&fast->next!=nullptr){fast=fast->next;slow=slow->next;} slow->next=slow->next->next;delete p;return head;}
};

java中new ListNode(0)常见用法详细区别(全)

左右指针

1 二分查找

链接

2 两数之和 – 有序数组

只要 数组有序,就应该想到 双指针技巧

力扣第 167

class Solution {public:vector<int> twoSum(vector<int>& numbers, int target) {int left,right;left = 0; right=numbers.size()-1;while(left < right){int sum = numbers[left]+numbers[right];if(sum == target) return {left+1,right+1};else if(sum < target) left++;else if(sum>target) right--;}return {-1,-1};}
};

3 反转数组

力扣第 344

class Solution {public:void reverseString(vector<char>& s) {int n = s.size();for (int left = 0, right = n - 1; left < right; ++left, --right) {swap(s[left], s[right]);}}
};

C++容器的swap()函数的三点说明
C++中的swap(交换函数)

4 滑动窗口算法

链接

以下四个问题:
1、当移动right扩大窗口,即加入字符时,应该更新哪些数据
2、什么条件下,窗口应该暂停扩大,开始移动left缩小窗口
3、当移动left缩小窗口,即移出字符时,应该更新哪些数据
4、我们要的结果应该在扩大窗口时还是缩小窗口时(何时)进行更新

针对 Leecode 76 题: 匹配对应字符及该字符个数
1、扩大窗口时,应更新窗口内包含目标子串的字符频数,每当完全匹配到一个字符时,更新一次当前窗口已经完全匹配到的字符数
2、当窗口已经完全包含所有目标子串字符时,开始缩小窗口
3、在收缩窗口前更新数据

LeetCode 76 题 最小覆盖子串

class Solution {public:string minWindow(string s, string t) {unordered_map<char,int> need,window; // 用于存储目标子串各字符频数 和 当前窗口中的字符频数for(char c : t) need[c]++; // 初始化 目标子串 各 字符频数// 搜索字符区间 (左开右闭) [left,right) 所以初始窗口为空int left=0,right=0; // 左右指针int valid = 0;  // 标记已匹配到的字符数int start=0,len=INT_MAX; // 记录最小子串起始位置及其长度,长度初始化为一个默认大值// 当 右指针right 超出字符串索引,结束while(right < s.size()){char c = s[right]; // 移入窗口内的元素right++; // 扩大窗口// 窗口内数据更新if(need.count(c)){ // 仅当与目标字符匹配时,更新window[c]++;if(window[c] == need[c]) // 仅当窗口内字符数与所需字符数相同时更新valid ++ ;}// 收缩窗口 (判断何时收缩窗口)while(valid == need.size()){ // 当窗口字符完全包含目标字符时,向左收缩窗口// 记录当前子串起始位置及其长度,仅当比上一子串小时更新if(right - left  < len){  // 因为搜索区间为[left,right) ,所以 right-left 即为窗口子串长度,无须 +1start = left;len = right-left;}// 移出窗口元素char d = s[left]; left ++; // 左移窗口// 窗口内数据更新if(need.count(d)){if(window[d] == need[d])valid --;window[d]--;}}}// 判断len 是否更新 未更新表示未搜索到最小子串,返回空字符串return len == INT_MAX ? "" : s.substr(start,len);}
};

LeetCode 567 字符串排列

class Solution {public:bool checkInclusion(string s1, string s2) {unordered_map<char,int> need,window;for(char c:s1) need[c]++;int left=0,right=0;int valid=0;while(right < s2.size()){char c=s2[right];right++;if(need.count(c)){window[c]++;if(window[c] == need[c])valid++;}// 当窗口等于目标子串长度时收缩窗口while(right - left >= s1.size()){if(valid == need.size()) return true;char d=s2[left];left++;if(need.count(d)){if(window[d] == need[d])valid --;window[d]--;}}}return false;}
};

LeetCode 第 438 : 找所有字母异位词

class Solution {public:vector<int> findAnagrams(string s, string p) {unordered_map<char,int> need,window;for(char c: p) need[c]++;int left=0,right=0;int valid=0;vector<int> start;while(right<s.size()){char c=s[right];right++;if(need.count(c)){window[c]++;if(window[c] == need[c])valid++;}// 窗口大小限制while(right - left >=p.size()){if(valid == need.size()) start.push_back(left);char d=s[left];left++;if(need.count(d)){if(window[d] == need[d])valid --;window[d]--;}}}return start;}
};

LeetCode 第 3 题 : 最长无重复子串

class Solution {public:int lengthOfLongestSubstring(string s) {unordered_map<char,int> window;int left=0,right=0;int res =0 ;while(right<s.size()){char c=s[right];right++;// 更新窗口window[c]++;// 收缩窗口while(window[c]>1){char d=s[left];left++;window[d]--;}// 更新结果res=max(res,right-left);}return res;}
};

leecode - 入门 -- 双指针总结相关推荐

  1. leecode - 入门 -- 双指针秒杀数组/链表题目

    目录 有序数组/链表去重 -- 快慢指针 移除元素 移动零 有序数组/链表去重 – 快慢指针 Leecode 26题 : 有序数组去重 快指针表示遍历数组到达的下标位置,慢指针表示下一个不同元素要填入 ...

  2. Leecode 入门--单链表-- 递归操作

    目录 反转单链表 1.递归反转整个链表 2.反转链表前 N 个节点 3.反转链表的一部分 整代码 K 个一组反转链表 迭代法反转 整代码 判断回文单链表 后序递归方式 空间复杂度优化 O(N)-> ...

  3. php+求二分查找递归算法,PHP二分查找(递归和循环)

    二分查找可以通过递归和循环来实现, 思路如下: 将要查找的数和中间数进行比较, 如果相等,则表示找到,返回下标 如果要查找的数小于中间这个数,则说明要查找的数分布在数组左边,修改right边界,使其等 ...

  4. 【面向校招】全力备战2023Golang实习与校招

    目录 1.自我介绍 2.GO 3.设计模式 4.Git 5.计算机网络 6.Mysql 7.Redis 8.操作系统 9.数据结构与算法 11.场景题 12.项目 wework灵鹿推 风铃草论坛 知识 ...

  5. Java入门算法(双指针篇)丨蓄力计划

    本专栏已参加蓄力计划,感谢读者支持 往期文章 一. Java入门算法(贪心篇)丨蓄力计划 二. Java入门算法(暴力篇)丨蓄力计划 三. Java入门算法(排序篇)丨蓄力计划 四. Java入门算法 ...

  6. 283移动零之Leecode—数组篇(双指针)

    移动零 链接: https://leetcode-cn.com/problems/move-zeroes/ 题目:给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相 ...

  7. Leetcode快速入门之第二节课: 使用双指针+区间法解决数组问题

    文章目录 1. 问题引入 2. Leetcode 26题分析 3. 双指针+区间法 引入 4. 数据验证 5. 其他问题 5.1 80题:删除有序数组中的重复项II 5.2 27题:删除元素 5.3 ...

  8. JavaScript——leetcode算法入门876. 链表的中间结点【双指针专题】

    题目描述 给定一个头结点为 head 的非空单链表,返回链表的中间结点. 如果有两个中间结点,则返回第二个中间结点. 示例 1: 输入:[1,2,3,4,5] 输出:此列表中的结点 3 (序列化形式: ...

  9. 【超硬核】还不知道怎么入门算法?这篇双指针让你吃到饱【力扣真题】+【算法图解】

最新文章

  1. Builder设计模式
  2. codeforces educational round110 e
  3. Web应用程序的简单插件系统
  4. uml+oopc嵌入式c语言开发精讲_嵌入式开发中更接近底层的汇编与C语言
  5. 35 SD配置-销售凭证设置-定义项目类别组
  6. 无插件实现大文件分片上传,断点续传
  7. 阿里云各个地域节点速度测试(测试点到阿里云各站点)
  8. 管理系统中的计算机应用数据库系统,自考管理系统中的计算机应用重点: 数据库系统(1)...
  9. C++ STL getline函数
  10. 电脑自带的服务器修复,还原或修复运行 Windows Server Essentials 的服务器
  11. 【spring】spring_IOC和DI
  12. java选择题库_java选择题库
  13. 各种风格的Android面试题进来了解一下,面试必问
  14. #(九)、江恩关注的古代数理必要的解读
  15. android脚本工具,安卓脚本编程软件
  16. 自学Python编程的第\七天----------来自苦逼的转行人
  17. ppt学习05——配色
  18. 剪切板的使用: 复制 粘贴
  19. 中国化肥产业发展现状及趋势分析,化肥产能过剩情况得到缓解「图」
  20. 顾问风采 | LF AI Data 基金会完成换届,堵俊平担任董事会主席、星爵担任会员总代表...

热门文章

  1. php中时间戳和正常日期的相互转化
  2. mylyn提交到JIRA的日期格式错误
  3. 终极破产的原因——20年玩儿钱与玩观念的的新经济
  4. HTML中ul等标签的用法
  5. 字符串首字母置为大写
  6. Python基础函数学习笔记(一)
  7. 大数据hadoop常见端口
  8. 大数据系统架构模块解析
  9. 大数据分析应注意哪些问题
  10. 大数据分析的重要性体现在哪里