双指针算法大概的模板
for(int i=0,j=0;i<n;i++)
{
while(i<j&&check(i,j))j++;
//根据每道题的具体逻辑
}
原本的暴力算法
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
check(i,j);
}
}
朴素算法的时间复杂度 O ( N 2 ) O(N^2) O(N2)
双指针算法就是将优化到 O ( N ) O(N) O(N),因为两个指针一共加起来移动的步数不会超过2*n
先写暴力,看i和j之间有没有单调关系,如果有单调关系就可以用双指针算法
这里的所谓的单调关系可以理解为,两个指针始终都只会单向运动,不会在某种情况下会“掉头运动”
给定一个长度为 n n n 的整数序列,请找出最长的不包含重复的数的连续区间,输出它的长度。
第一行包含整数 n n n。
第二行包含 n n n 个整数(均在 0 ∼ 1 0 5 0 \sim 10^5 0∼105 范围内),表示整数序列。
共一行,包含一个整数,表示最长的不包含重复的数的连续区间的长度。
1 ≤ n ≤ 1 0 5 1 \le n \le 10^5 1≤n≤105
5
1 2 2 3 5
3
#include
using namespace std;
const int N = 100010;
int q[N];//存放数列
int s[N];//记录哪些数字在当前计算长度的数列区间中
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>q[i];
}
int res=0;
for(int i=0,j=0;i<n;i++)
{
s[q[i]]++;//q[i]存在于当前子序列,故s[q[i]]++;
while(j<=i&&s[q[i]]>1)//s[q[i]]>1说明q[i]重复了,这个时候就开始移动j指针
{
s[q[j]]--;
j++;
}//j指针停止移动,新的不重复子序列生成
res=max(res,i-j+1);//更新新的最长连续不重复子序列的长度
}
cout<<res<<endl;
return 0;
}
最近在两道leetcode的双指针算法题中发现两道用快慢双指针的算法题
给定一个头结点为
head
的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
解题的思路在于,使用快慢双指针,快指针每次走两步,慢指针每次只走一步
当快指针fast
此时慢指针一定处于链表中间位置
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* middleNode(ListNode* head) {
ListNode* p=head;
ListNode* q=head;
while(p!=nullptr&&p->next!=nullptr)
{
q=q->next;
p=p->next->next;
}
return q;
}
};
给你一个链表,删除链表的倒数第
n
个结点,并且返回链表的头结点。
解题的思路在于,使用快慢双指针,两个指针一开始都指向head
节点,让快指针先走n步
然后再和慢指针一起运动,这样,当快指针走到结尾的时候,慢指针就会在倒数第n个位置
但是由于是要删除倒数第n个节点,因此最好一开始慢指针就指向单链表的头节点(哑节点)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* p=head;
ListNode* o=new ListNode(0,head);
ListNode* q=o;
while(n--)
{
p=p->next;
}
while(p)
{
q=q->next;
p=p->next;
}
q->next=q->next->next;
return o->next;
}
};