双指针技巧解题-链表题目
1.合并两个有序链表

package com.algorithm202305.linkedlist;
/**
* 合并两个有序列表 https://leetcode.cn/problems/merge-two-sorted-lists/
* 引用虚拟节点和一个指向虚拟节点的引用p 它只是作为一个指针在构建新的链表时使用,并最终帮助确定合并后链表的尾部
*/
public class Demo1 {
public static class ListNode {
int val;
ListNode next;
ListNode() {
}
ListNode(int val) {
this.val = val;
}
ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
public static void main(String[] args) {
ListNode listNode1 = new ListNode(2);
ListNode listNode3 = new ListNode(4);
listNode1.next = listNode3;
ListNode listNode2 = new ListNode(3);
ListNode listNode4 = new ListNode(5);
ListNode listNode5 = new ListNode(4);
listNode2.next = listNode4;
listNode4.next = listNode5;
traverse(mergeTwoLists(listNode1, listNode2));
}
public static ListNode mergeTwoLists(ListNode p1, ListNode p2) {
// 虚拟头结点
ListNode dummy = new ListNode(-1), p = dummy;//p指针合并链表
while (p1 != null && p2 != null) {
// 比较 p1 和 p2 两个指针
// 将值较小的的节点接到 p 指针
if (p1.val > p2.val) {
p.next = p2;
p2 = p2.next;
} else {
p.next = p1;
p1 = p1.next;
}
// p 指针不断前进
p = p.next;
}
if (p1 != null) {
p.next = p1;
}
if (p2 != null) {
p.next = p2;
}
return dummy.next;
}
static void traverse(ListNode head) {
// 递归访问 head.val
System.out.print(head.val + " ");
if (head.next != null) {
traverse(head.next);
}
}
}
2.单链表分解

package com.algorithm202305.linkedlist;
/**
* 单链表的分解
* 在合并两个有序链表时让你合二为一,而这里需要分解让你把原链表一分为二。
* 具体来说,我们可以把原链表分成两个小链表,一个链表中的元素大小都小于 x,另一个链表中的元素都大于等于 x,最后再把这两条链表接到一起,就得到了题目想要的结果。
*/
public class Demo2 {
public static void main(String[] args) {
ListNode l1 = new ListNode(1);
ListNode l2 = new ListNode(4);
ListNode l3 = new ListNode(3);
ListNode l4 = new ListNode(2);
ListNode l5 = new ListNode(5);
ListNode l6 = new ListNode(2);
l1.next = l2;
l2.next = l3;
l3.next = l4;
l4.next = l5;
l5.next = l6;
traverse(partition(l1,3));
}
public static class ListNode {
int val;
ListNode next;
ListNode() {
}
ListNode(int val) {
this.val = val;
}
ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
static ListNode partition(ListNode head, int x) {
//虚拟节点1 存放小于x的节点
ListNode dummy1 = new ListNode(-1);
//虚拟节点2 存放大于等于x的节点
ListNode dummy2 = new ListNode(-1);
//p1,p2负责生成dummy1和dummy2的结果链表
ListNode p1 = dummy1,p2 = dummy2;
ListNode p = head;
while (p != null){
if(p.val < x){
p1.next = p;
p1 = p1.next;
}else {
p2.next = p;
p2 = p2.next;
}
// 断开原链表中的每个节点的 next 指针 //考公
ListNode temp = p.next;
p.next = null;
p = temp;
}
p1.next = dummy2.next;
return dummy1.next;
}
static void traverse(ListNode head) {
// 递归访问 head.val
System.out.print(head.val + " ");
if (head.next != null) {
traverse(head.next);
}
}
}