算法入门之双指针
1、什么是指针?
在百度百科中这样规定:指针是一个占据存储空间的实体在这一段空间起始位置的相对距离值。在C/C++语言中,指针一般被认为是指针变量,指针变量的内容存储的是其指向的对象的首地址,指向的对象可以是变量(指针变量也是变量),数组,函数等占据存储空间的实体。
即:指针就是变量
2、什么是双指针?
指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个相同方向或者相反方向的指针进行扫描,从而达到相应的目的。即:指向两个变量的指针
3、常见的双指针类型有哪些?
-
普通双指针:两个指针方向往同一个方向移动
-
对撞双指针:两个指针面对面移动
-
快慢双指针:慢指针和快指针,即一个指针移动速度快,一个指针移动速度慢。
4、题型练习
题型1:对撞双指针练习
力扣:881、救生艇
题目:第 i 个人的体重为 people[i],每艘船可以承载的最大重量为 limit。
每艘船最多可同时载两人,但条件是这些人的重量之和最多为 limit。
返回载到每一个人所需的最小船数。(保证每个人都能被船载)。
示例:
输入:people = [1,2], limit = 3
输出:1
解释:1 艘船载 (1, 2)
思路:利用对撞链表来完成,创建一个数组,对数组进行排序,创建两个指针,分别指向数组后和尾部循环遍历数组元素,当两个指针所在元素相加小于等于limit时,分别指向下一个元素,否组,尾部指针指向下一个元素,直到数组元素遍历完为止。
class Solution {
public int numRescueBoats(int[] people, int limit) {
//安全校验
if (people==null||people.length<=0){
return -1;
}
//对数组进行排序
Arrays.sort(people);
//定义指针
int perPointer=0;
int tailPointer=people.length-1;
//定义船的数量
int shipNum=0;
//遍历元素
while (perPointer<tailPointer){
if (people[perPointer] + people[tailPointer]<=limit) {
perPointer++;
tailPointer--;
shipNum++;
}else {
tailPointer--;
}
}
//返回船的数量
return shipNum;
}
}
题型2:快慢双指针
力扣:141、环形链表
题目:如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false 。
示例:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
思路:快慢指针同时从链表的一端出发,当快指针第二次遇到慢指针的时候,证明这是一个环形链表。
public class Solution {
public boolean hasCycle(ListNode head) {
if (head==null){
return false;
}
//快慢指针,快指针在第二次遇到慢指针时,表明这是一个环形链表
//定义快慢指针
ListNode fast=head;
ListNode slow=head;
while (fast!=null&&fast.next!=null) {//快指针不为null,快指针的下一个元素不为null
slow=slow.next;//慢指针指向下一个元素
fast=fast.next.next;//快指针指向下一个下一个元素
if (slow==fast){//当快指针和慢指针遍历元素相等时,为环形链表
return true;
}
}
return false;
}
}