1.介绍
双指针,指的是在遍历对象的过程中,使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,从而达到相应的目的。经常用在数组和链表数据结构中, 双指针算法通常不难,双指针算法是基于暴力解法的优化,它们是很好的学习算法的入门问题。 双指针在平时运用中,一般分为两类,“快慢指针”,用于解决链表中的问题;“左右指针”,用于解决数组中的问题,比如二分搜索。
2.快慢指针
快慢指针,一般会初始化链表的头结点 head,快指针 fast在前,慢指针 slow在后,通过指针移动,来解决链表中的问题。
题目描述
给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false 。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
题目解析
判断单链表是否有环,常用算法就是双指针,fast指针跑得快,slow指针跑得慢。如果没有环,fast指针最终会遇到null;如果有环,fast指针最终会超slow指针1圈,和slow指针相遇。
代码实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
bool hasCycle(struct ListNode *head) {
struct ListNode *fast = head;
struct ListNode *slow = head;
while (fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast)
return true;
}
return false;
}
3.左右指针
左右指针,就是的数组里的两个索引值,用left和right表示。
题目描述
给定一个已按照 非递减顺序排列的整数数组numbers ,请你从数组中找出两个数满足相加之和等于目标数target 。
函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。
示例 1:
输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2
题目解析
题目中数组是有序的,首先会想到用双指针实现,类似于二分查找解法。
如果 nums[left] + nums[right] = target
,则下标 left
和 right
即为要寻找的下标;
如果 nums[left] + nums[right] > target
,则 left++
接着查找;
如果 nums[left] + nums[right] < target
,则 right
接着查找。
代码实现
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* twoSum(int* numbers, int numbersSize, int target, int* returnSize){
int *res = (int*)malloc(sizeof(int) * 2);
int left = 0;
int right = numbersSize - 1;
res[0] = -1;
res[1] = -1;
*returnSize = 2;
while (left < right) {
if (numbers[left] + numbers[right] == target) {
res[0] = left + 1;
res[1] = right + 1;
return res;
}
else if (numbers[left] + numbers[right] < target) {
left++;
}
else {
right--;
}
}
return res;
}