算法入门之双指针(Leetcode)
前言
双指针是针对于有顺序的数据结构一种方法和技巧,通常用于线性的数据结构中,如链表和数组有时也会用在图算法中。
1.碰撞指针
1.1应用 概念
碰撞指针分为左右两个指针,从左右两方按照各自的刷新规则向中间靠拢遍历。遍历链表或者数组。
碰撞指针经常见于二分法中 。
1.2案例分析(leetcode 35题)
题目:
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。题目链接
示例1:
输入: nums = [1,3,5,6], target = 5
输出: 2
示例2:
输入: nums = [1,2,3,4,5,6,7,8,9], target = 8
输出: 7
解题思路:
代码:
class Solution {
public:
int searchInsert(vector<int>& nums, int target)
{
int mid,left=0,right=nums.size()-1;//初始起始,中点值
while(left<=right)//当左右指针相等的时候证明数组已经遍历完了。
{
mid=left+(right-left)/2;
if(target==nums[mid])
{return mid;}
else if(target>nums[mid])
{left=mid+1;}
else
{right=mid-1;}
};
return right+1;
};
};
2.快慢指针
2.1 应用 概念
- 计算链表的中点:
快慢指针从头节点出发,每轮迭代中,快指针向前移动两个节点,慢指针向前移动一个节点,最终当快指针到达终点的时候,慢指针刚好在中间的节点。 - 求链表倒数第k个元素:
设定快慢两个指针,让其中快指针先走k步,然后快慢指针以相同的速度移动,当快指针到达终点,则慢指针正好位于倒数第k个元素。 - 判断链表是否有环:
使用快慢指针,当链表中存在环时,两个指针最终会在环中相遇。 - 判断链表中环的起点:
- 求链表中环的长度:
只要相遇后一个不动,另一个前进直到下一次相遇算一下走了多少步就好了
2.2 案例分析(leetcode 19题)
题目:
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。题目链接
示例1:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例2:
输入:head = [1], n = 1
输出:[]
解题思路如下:
这里头部引入哑节点,是为了让头节点变成普通节点。
代码:
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n)
{
ListNode* fast=head;
ListNode* slow;
ListNode* temp=new ListNode(0,head);//引进哑节点,因为想把头节点这个特殊的节点当成一个普通节点来看。
slow=temp;
int i=0;
while(i<n)
{
fast=fast->next;
i++;
}//让快指针先领先n个位置
while(fast)
{
fast=fast->next;
slow=slow->next;
}
slow->next=slow->next->next;//当快指针到达链表末尾时候,让慢指针指向下下一个地址(即删除下一位)
return temp->next;//删除增加的0头,从后面一位开始读取,temp->next是一个地址,指向slow的头地址。
delete temp;
}
};
3.滑动窗口法
3.1 概念
滑动窗口法:可以理解为用两个指针作为窗口的左右框。每当右端指针扩展,窗口就会更新,每次的新窗口都需要判断是否还是满足要求的窗口,如果不是满足要求的窗口需要对窗口左端进行裁剪(即左指针指向下一个值)。
3.2 案例分析 <leetcode 3题 >
无重复字符的最长子串
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。题目链接
示例1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
解题方法:
流程框图如下:
代码:
class Solution {
public:
int lengthOfLongestSubstring(string s)
{
int start=0,end=0,result=0,length=0;
int n=s.size();
while(end<n)//判断是否到字符串的结尾
{
char temp=s[end];//把新加入的字符设置为标志位
//判断新加入的字符在原字符串里面有没有。
for( int index=start;index<end;index++)//index=end的话窗口不能滑动起来。
{
if(s[index]==temp)//如果发现第index个字符与新加入的字符相同
{
//开始滑动窗口
start=index+1;//让起始点变成这个index+1,为了满足题目要求
length=(end-start);//刷新length长度
break;
}
}
length++;//如果加入
end++;//无论重不重复都要end+1;
result=max(length,result);
}
return result;
}
};
ps:算法萌新,有错误还望指正 谢谢阅读。