algo›problem
链表解题技巧
1、合并两个有序链表
leetcode 第 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 dummy = new ListNode(-1), p = dummy;
ListNode p1 = list1, p2 = list2;
while(p1!=null && p2 !=null){
if(p1.val > p2.val){
p.next = p2;
p2 = p2.next;
}
else{
p.next = p1;
p1 = p1.next; // 指针往后移动一位
}
p = p.next; // 移动p
}
// 添加上后面没有循环完的节点
if(p1!=null){
p.next = p1;
}
if(p2!=null){
p.next = p2;
}
return dummy.next;
}
}
2、分割链表
/**
* 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) {
ListNode dummy1 = new ListNode(-1); // 两个虚拟头结点
ListNode dummy2 = new ListNode(-1);
ListNode p1 = dummy1, p2 = dummy2; // 两个可移动的节点
ListNode p = head;
while(p != null){
if(p.val >= x){ // 判断节点值的大小,放到对应链表节点后面
p2.next = p;
p2 = p2.next;
}
else{
p1.next = p;
p1 = p1.next;
}
ListNode tmp = p.next; // 原链表指针移动
p.next = null;
p = tmp;
}
// 合并两个链表
p1.next = dummy2.next; // 链接两个链表
return dummy1.next; // 返回链表。
}
}
3、合并 k 个升序的链表
这里用到一个二叉堆的数据结构, 先明白如何用,再说是怎样实现的, 就是使用一个优先级队列来处理,先把条件给出来的链表放到优先级队列里面,后面每次在 pull 出来最小的节点,放到虚拟节点的后面。
/**
* 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.length == 0){
return null;
}
ListNode dummy = new ListNode(-1);
ListNode p = dummy;
PriorityQueue<ListNode> pq = new PriorityQueue<>(
lists.length, (a, b)->(a.val - b.val) // a.val - b.val 最小堆
);
// put ListNode head in priorityQueue
for(ListNode head: lists){
if(head!= null){ // if head != null
pq.add(head);
}
}
while(!pq.isEmpty()){ // pq is not empty, pull minest node
ListNode node = pq.poll();
p.next = node;
if(node.next!=null){
pq.add(node.next);
}
p = p.next;
}
return dummy.next;
}
}