一、双指针法简介
所谓双指针,指的是在遍历对象的过程中,不是普通的使用单个指针(索引、游标、指针或可迭代对象皆可)进行访问,而是使用两个相同方向或者相反方向的指针进行扫描,从而达到相应的目的。
换言之,双指针法充分使用了数组有序这一特征,从而在某些情况下能够简化一些运算。
二、双指针法的应用
(1)和为sum的两个数
#include
#include
#include
using namespace std;
tuple<int, int> twoSum(vector<int> &numbers, const int &target)
{
//使用双指针法,一个指向数组头,一个指向数组尾,然后向中间收缩
int i = 0, j = numbers.size() - 1;
while (i < j)
{
int sum = numbers[i] + numbers[j];
if (sum == target)
return make_tuple(i + 1, j + 1);
else if (sum < target)//和比目标值小,则右移较小的元素,否则左移较大的元素
++i;
else
--j;
}
}
int main(int argc, char const *argv[])
{
vector<int> vec = {2, 7, 11, 15};
int a = 9;
int f1, f2;
std::tie(f1, f2) = twoSum(vec, a);
cout << f1 << " " << f2;
return 0;
}
(2)判断链表是否有环
#include
#include
#include
using namespace std;
typedef struct ListNode
{
int data;
ListNode *next;
}*lst;
bool hasCycle(lst root)
{
if (root == nullptr)
return false;
lst l1 = root;//一个指针每次走一步
lst l2 = root->next;//另一个指针走两步
while (l1 != nullptr && l2 != nullptr && l2->next != nullptr)
{
if (l1 == l2)//如果两个指针相遇则说明链表有环
return true;
else
{
l1 = l1->next;
l2 = l2->next->next;
}
}
return false;
}
int main(int argc, char const *argv[])
{
lst ptr1 = new ListNode;
lst ptr2 = new ListNode;
lst ptr3 = new ListNode;
lst ptr4 = new ListNode;
ptr1->data = 1;
ptr1->next = ptr2;
ptr2->data = 2;
ptr2->next = ptr3;
ptr3->data = 3;
ptr3->next = ptr4;
ptr4->data = 4;
ptr4->next = ptr2;//有环
cout << hasCycle(ptr1);
system("pause");
return 0;
}
(3)奇偶排序
给定一个数组,数组中元素有奇数有偶数。要求对数组进行处理,使得数组的左边为奇数,右边为偶数:
void partition(int *arr,int n)
{
int i = 0;
int j = n-1;
while(1)
{
while(i%2 == 1) i++;//找到左边第一个不为奇数的位置。
while(i%2 == 0) j--;//找到右边第一个不为偶数的位置。
if(i//交换两个数的位置,重新遍历。
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
(4)求单链表的中间元素
/*
*取单链表的中间元素,如果单链表元素为奇数个,那么去中间的元素,如果是偶数个,取后面的一个元素。
*/
linkList getMidElem(const linkList L)
{
if(L == NULL)
{
return NULL;
}
linkList first = L;
linkList second = L;
//采用两个指针,初始化都指向链表表头,移动开始时,快指针移动两步,
//慢指针移动一步。当快指针的next为null或者快指针为null的时候,
//慢指针所指的就是单链表的中间元素。
while(first != NULL && first->next != NULL)
{
first = first->next->next;
second = second->next;
}
return second;
}
(5)给出n个数,问最多能组成多少个三角形
思路 :枚举b(第2边),一个指针指向a,另一个指向c,如果满足a+b>c就是一个三角形,同时得知 b后面的数+c>a一定成立,然后end–。如果b+c