双指针技巧秒杀七道链表题目
基于labuladong的算法网站的文章,双指针秒杀七道链表题目
1、合并两个有序链表
力扣第21题,合并两个有序链表
[21]合并两个有序链表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
// 创建新链表的虚拟头节点
ListNode head = new ListNode(0);
// 三个指针
ListNode p = head, p1 = list1, p2 = list2;
while (p1 != null && p2 != null) {
if (p1.val <= p2.val) {
p.next = p1;
p1 = p1.next;
} else {
p.next = p2;
p2 = p2.next;
}
p = p.next;
}
// 没遍历完的链表续上
if (p1 != null) {
p.next = p1;
}
if (p2 != null) {
p.next = p2;
}
return head.next;
}
}
2、单链表的分解
力扣第86题,分隔链表
[86]分隔链表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode partition(ListNode head, int x) {
// 相当于将一个链表分成两个链表:小于x的链表&&大于或等于x的链表
// 定义两个新链表的头节点
ListNode small = new ListNode(0);
ListNode big = new ListNode(0);
// 三个指针
ListNode p = head, p1 = small, p2 = big;
while (p != null) {
// 需要保存下一个节点
ListNode next = p.next;
// 判断当前节点的值和x的大小关系
if (p.val < x) {
p1.next = p;
p1 = p1.next;
} else {
p2.next = p;
p2 = p2.next;
}
p.next = null;// 断开指向
p = next;// 指向正确的位置
}
// 最后返回的结果将小链表的末尾连上大链表的真实头节点
p1.next = big.next;
return small.next;
}
}
3、合并k个有序链表
力扣第23题,合并k个升序链表
[23]合并K个升序链表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
// 先行条件判断
if (lists == null || lists.length == 0) {
return null;
}
ListNode head = new ListNode(0);// 返回的虚拟头节点
// 采用优先级队列
PriorityQueue<ListNode> queue = new PriorityQueue<>((node1, node2) -> node1.val - node2.val);
// 首先将所有的头节点加入的优先级队列中
for (ListNode node : lists) {
if (node != null) {
queue.add(node);
}
}
ListNode p = head;
// 遍历优先级队列中的元素
while (!queue.isEmpty()) {
// 弹出一个元素
ListNode cur = queue.poll();
if (cur.next != null) {
queue.add(cur.next);
}
p.next = cur;
p = p.next;
}
// 返回的结果
return head.next;
}
}
4、单链表的倒数第k个节点
力扣第19题,删除链表的倒数第N个节点
[19]删除链表的倒数第 N 个结点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
// 找到倒数第n个节点,让倒数第n+1个节点指向倒数第n-1个节点
// 虚拟头节点,方便找到倒数第k+1个节点
ListNode node = new ListNode(0);
node.next = head;
// 找到倒数第n+1个节点
ListNode cur = getLastK(node, n + 1);
// 重新指向
cur.next = cur.next.next;
return node.next;
}
// 编写一个找到倒数第K个节点的函数
ListNode getLastK(ListNode head, int k) {
// 定义两个指针
ListNode p1 = head, p2 = head;
while (--k >= 0) {
p2 = p2.next;// 先让p2走
}
// p1和p2同时走
while (p2 != null) {
p1 = p1.next;
p2 = p2.next;
}
return p1;
}
}
5、单链表的中点
力扣第876题,链表的中间结点
[876]链表的中间结点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode middleNode(ListNode head) {
// 快慢指针
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
}
6、判断链表是否包含环
力扣第141题,环形链表
[141]环形链表
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
// 采用快慢指针
ListNode slow = head, fast = head;
// 遍历链表
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
return true;
}
}
// 没找到
return false;
}
}
7、两个链表是否相交
力扣第160题,相交链表
[160]相交链表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
// 利用双指针进行遍历,遍历的链表都为A+B链表
ListNode p1 = headA, p2 = headB;
// p1和p2相等的条件为:要么找到相交节点,要么就是走到链表尽头都为null
while (p1 != p2) {
if (p1 == null) {
p1 = headB;
} else {
p1 = p1.next;
}
if (p2 == null) {
p2 = headA;
} else {
p2 = p2.next;
}
}
return p1;
}
}