文章目录
- 1、双指针算法
- 1.1 对撞双指针
- 1.2 快慢双指针
- 2、leetcode141:环形链表
- 3、leetcode881:救生艇
1、双指针算法
用两个指针来共同解决一个问题:
1.1 对撞双指针
比如先有一个有序的数组array
int[] array = {1, 4, 5, 7, 9}
先要找两个数,使得其和为12,且两个数不能相同。最先想到的是,两层循环,遍历array,如外层 i = 1,内层循环 j = 4 5 7 9,外层 i = 4,内层循环 j = 1 5 7 9……,但这样时间复杂度为O(n^2)。用对撞双指针优化:
对撞前即p1 <= p2,p1 = p2时,说明二者指向同一个元素,再往下就错开了。
1.2 快慢双指针
比如现在要检测一个链表是否为环形:
此时可用快慢双指针,慢的一次走一步,s = s.next,快的一次走两步,f = f.next.next,二者同时从队首出发:
移动三次后,快慢指针相遇了,这说明是个环形,否则二者不会相遇。
2、leetcode141:环形链表
和上面的快慢指针一样,代码实现:
public class P141 {public static boolean checkCycle(ListNode head) {if (null == head) {return false;}// 快慢指针,均从头节点开始ListNode slowPoint = head;ListNode fastPoint = head;// 这里的条件无需判断慢指针,如果是环形,大家都不为null// 如果不是环形,那一定是快指针先走完而出现null// 因此退出循环的条件是:快指针走完了,而快指针一次两步,所以走完的条件是当前已为空或者不够两步了while(fastPoint != null && fastPoint.next != null) {// 慢指针一次一步,快指针一次两步slowPoint = slowPoint.next;fastPoint = fastPoint.next.next;if (slowPoint.equals(fastPoint)){return true;}}return false;}
}
测试:
//链表节点类
public class ListNode {int val;ListNode next;public ListNode() {}public ListNode(int val, ListNode next) {this.val = val;this.next = next;}@Overridepublic String toString() {return "ListNode{" +"val=" + val +", next=" + next +'}';}
}
public class P141 {public static void main(String[] args) {ListNode tailNode = new ListNode(1, null);ListNode node4 = new ListNode(2, tailNode);ListNode node3 = new ListNode(2, node4);ListNode node2 = new ListNode(1, node3);ListNode node1 = new ListNode(0, node2);ListNode head = new ListNode(9, node1);tailNode.setNext(head);System.out.println(checkCycle(head));}
}
3、leetcode881:救生艇
其实本质是两个人的体重之和问题,和上面提到的对撞指针很像,不过一个是等号,一个是小于号,因此考虑先给所有人的体重从小到大排个序(因为排序是对撞指针移动的基础前提)
public class P881 {public static int calcMinShipNum (int[] weight, int limit) {if (weight == null || weight.length == 0 || limit <= 0) {return 0;}Arrays.sort(weight);// 头尾指针的位置int i = 0;int j = weight.length - 1;// 船的数量int res = 0;while (i <= j) {if (weight[i] + weight[j] < limit) {// 两个人可以乘一条船走,船的数量+1,头指针向右一位,尾指针向左一位i = i + 1;j = j - 1;} else {// 两个人体重总和超重,只让最胖的人走j = j - 1;}// 不管这轮是载走了首位两个人,还是只能带走最胖的那个人,船的数量都+1res = res + 1;}return res;}
}
测试:
public class P881 {public static void main(String[] args) {int[] weightArray = {3,5,3,4};System.out.println(calcMinShipNum(weightArray, 5));}
}