leecode - 入门 -- 双指针总结
目录
- 快慢指针
- 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 - 入门 -- 双指针总结相关推荐
- leecode - 入门 -- 双指针秒杀数组/链表题目
目录 有序数组/链表去重 -- 快慢指针 移除元素 移动零 有序数组/链表去重 – 快慢指针 Leecode 26题 : 有序数组去重 快指针表示遍历数组到达的下标位置,慢指针表示下一个不同元素要填入 ...
- Leecode 入门--单链表-- 递归操作
目录 反转单链表 1.递归反转整个链表 2.反转链表前 N 个节点 3.反转链表的一部分 整代码 K 个一组反转链表 迭代法反转 整代码 判断回文单链表 后序递归方式 空间复杂度优化 O(N)-> ...
- php+求二分查找递归算法,PHP二分查找(递归和循环)
二分查找可以通过递归和循环来实现, 思路如下: 将要查找的数和中间数进行比较, 如果相等,则表示找到,返回下标 如果要查找的数小于中间这个数,则说明要查找的数分布在数组左边,修改right边界,使其等 ...
- 【面向校招】全力备战2023Golang实习与校招
目录 1.自我介绍 2.GO 3.设计模式 4.Git 5.计算机网络 6.Mysql 7.Redis 8.操作系统 9.数据结构与算法 11.场景题 12.项目 wework灵鹿推 风铃草论坛 知识 ...
- Java入门算法(双指针篇)丨蓄力计划
本专栏已参加蓄力计划,感谢读者支持 往期文章 一. Java入门算法(贪心篇)丨蓄力计划 二. Java入门算法(暴力篇)丨蓄力计划 三. Java入门算法(排序篇)丨蓄力计划 四. Java入门算法 ...
- 283移动零之Leecode—数组篇(双指针)
移动零 链接: https://leetcode-cn.com/problems/move-zeroes/ 题目:给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相 ...
- Leetcode快速入门之第二节课: 使用双指针+区间法解决数组问题
文章目录 1. 问题引入 2. Leetcode 26题分析 3. 双指针+区间法 引入 4. 数据验证 5. 其他问题 5.1 80题:删除有序数组中的重复项II 5.2 27题:删除元素 5.3 ...
- JavaScript——leetcode算法入门876. 链表的中间结点【双指针专题】
题目描述 给定一个头结点为 head 的非空单链表,返回链表的中间结点. 如果有两个中间结点,则返回第二个中间结点. 示例 1: 输入:[1,2,3,4,5] 输出:此列表中的结点 3 (序列化形式: ...
- 【超硬核】还不知道怎么入门算法?这篇双指针让你吃到饱【力扣真题】+【算法图解】
最新文章
- Builder设计模式
- codeforces educational round110 e
- Web应用程序的简单插件系统
- uml+oopc嵌入式c语言开发精讲_嵌入式开发中更接近底层的汇编与C语言
- 35 SD配置-销售凭证设置-定义项目类别组
- 无插件实现大文件分片上传,断点续传
- 阿里云各个地域节点速度测试(测试点到阿里云各站点)
- 管理系统中的计算机应用数据库系统,自考管理系统中的计算机应用重点: 数据库系统(1)...
- C++ STL getline函数
- 电脑自带的服务器修复,还原或修复运行 Windows Server Essentials 的服务器
- 【spring】spring_IOC和DI
- java选择题库_java选择题库
- 各种风格的Android面试题进来了解一下,面试必问
- #(九)、江恩关注的古代数理必要的解读
- android脚本工具,安卓脚本编程软件
- 自学Python编程的第\七天----------来自苦逼的转行人
- ppt学习05——配色
- 剪切板的使用: 复制 粘贴
- 中国化肥产业发展现状及趋势分析,化肥产能过剩情况得到缓解「图」
- 顾问风采 | LF AI Data 基金会完成换届,堵俊平担任董事会主席、星爵担任会员总代表...