快慢指针,双指针

it2023-06-21  61

一,快慢指针

快慢指针也被称为Hare&Tortoise算法,两个在数组(链表)中以不同速度移动的指针。

应用场景: 处理链表或数组中的循环的问题,例如判断链表是否为环状找链表中点或需要知道特定元素的位置 leetcode141环形链表 class Solution { public: bool hasCycle(ListNode *head) { ListNode* fast=head; ListNode* slow=head; while(fast&&fast->next){ fast=fast->next->next; slow=slow->next; if(fast==slow) return true; } return false; } }; leetcode142,返回入环的第一个节点

用快慢指针可以判断出链表是否有环,

假设在z 点 fast指针和slow 指针相遇。x-y 长度为a, y-z 长度为 b , z-y 长度为c。

则:slow 指针走了 a+b 的距离。 fast 指针走了 a + n(b + c)+ b 的距离。(可能不仅绕了一圈而是绕环走了n圈)

fast指针的速度是slow 指针速度的2倍。 所以a + b + n(b + c) = 2 (a + b), 简化得 a+b = n(b + c)。 因为我们想要求 a 的距离, 所以我们移动方程 得到 a = (n-1)b + n c 。

仔细观察上面的等式。 考虑它的含义, 即c 总比b 多一次, 这就意味着, 我们再放两个指针, first放在x ,second放在z ,这次保持速度一致, first 跑到y , second 也会跑到y。所以,当它们相遇,就是cycle的起点。

class Solution { public: ListNode *detectCycle(ListNode *head) { ListNode* slow=head; ListNode* fast=head; while(fast&&fast->next){ slow=slow->next; fast=fast->next->next; if(fast==slow){ ListNode *l1=head; ListNode *l2=fast; while(l1!=l2) { l1=l1->next; l2=l2->next; } return l1; } } return 0; } }; leetcode 234判断是否为回文链表

思路:先使用快慢指针找到中点,把前半部分逆转,再和后半部分链表逐个比较

class Solution { public: bool isPalindrome(ListNode* head) { if(!head || !head->next) return 1; ListNode *fast = head, *slow = head; ListNode *p, *pre = NULL; while(fast && fast->next){ p = slow; slow = slow->next; //快慢指针,寻找链表的中点 fast = fast->next->next; p->next = pre; //遍历慢指针,且翻转 pre = p; } if(fast) //奇数个节点时,fast为最后一个节点,需跳过中间节点;偶数个节点,fast为NULL slow = slow->next; while(p){ //前半部分和后半部分比较 if(p->val != slow->val) return 0; p = p->next; slow = slow->next; } return 1; } };

二,双指针

指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,从而达到相应的目的。这里指左右指针。

二分查找,两数之和,反转数组,滑动窗口

 

最新回复(0)