双指针算法
对撞指针
给定一个有序整型数组和一个整数target,在其中寻找两个元素,十其和为target,返回这两个数的索引
如:[2,7,11,15],target=9
输出 [1,2]
最直接的解法就是暴力解法,双层遍历,这样他的时间复杂度就是O(n^2)
但是暴力解法没有利用他的已知条件,就是有序
双指针指定数组左右两个下标,通过将两个下标向中间移动来求出解 Arr[i]+Arr[j]==target
代码
#include<iostream> using namespace std; pair<int, int> DoublePointer(int* Arr, int ArrLen,int Target); int main(void) { int ArrLen; cin >> ArrLen; int* Arr = new int[ArrLen]; for (int i = 0; i < ArrLen; ++i) cin >> Arr[i]; int Target; cin >> Target; pair<int,int> Rslt=DoublePointer(Arr, ArrLen, Target); cout << Rslt.first << " " << Rslt.second << endl; system("pause"); return 0; } pair<int, int> DoublePointer(int* Arr, int ArrLen,int Target) { int L = 0; int R = ArrLen - 1; while (L < R) { if ((Arr[L] + Arr[R]) == Target) return pair<int, int>(L+1, R+1); if ((Arr[L] + Arr[R]) < Target) ++L; if ((Arr[L] + Arr[R]) > Target) --R; } return pair<int,int>(-1,-1); }
其他的指针对撞问题
leetcode125
给定一个字符串,只看其中的数字和字母,忽略大小写,判断这个字符串是否为回文串
leetcode344
给定一个字符串,返回这个字符串的倒序字符串(限制时间复杂度)
ij一个头一个尾,然后交换ij位置即可
leetcode345
给定一个字符串,将该字符串中的元音字母反转
快慢指针
给定一个链表,返回链表开始入环的第一个节点,如果链表无环,则返回null
为了表示给定链表中的环,使用整数pos来表示链表尾连接到链表中的位置,索引从0开始,如果pos是-1则表示链表中没有环
暴力算法:将链表的所有点都放到一个集合中,走到环时循环出现的第一个数字在集合中定位即可,但是如果显示时间复杂度为O(n),那么暴力解法行不通
快慢指针:跑的快的人会给跑得慢的人套圈,快指针一次走两个节点,慢指针一次只走一个节点,他们最终会在环的某个位置相遇
如果链表没有环,那么快指针走到链表末尾直接返回NULL
如果快慢指针相遇,此时再加一个慢指针,两个慢指针一个从链表首个节点出发,另一个从快慢指针相遇的位置出发,这两个慢指针再次相遇的地方就是环的入口
伪代码
LinkList FastSlowPointer(LinkList &HeadNode) { LinkList FastPointer, SlowPointer; FastPointer = HeadNode; SlowPointer = HeadNode; while (FastPointer != NULL) { // 先走一步 FastPointer = FastPointer.Next; if (FastPointer == NULL) return NULL; // 快慢都走一步 FastPointer = FastPointer.Next; SlowPointer = SlowPointer.Next; if (SlowPointer == FastPointer) break; } if (FastPointer == NULL) return NULL; LinkList p1 = SlowPointer; LinkList p2 = HeadNode; while (p1 != p2) { p1 = p1.Next; p2 = p2.Next; } return p1; }
无情的摸鱼机器