链表双指针
分解是设置一个p在输入的链表head上游走,p1和p2是在要分解的两个链表游走
合并是设置一个p在要合并的链表上游走,设置p1和p2在输入的链上游走
21. 合并两个有序链表
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode p1=list1;
ListNode p2=list2;
ListNode dummy=new ListNode(-1);
ListNode p=dummy;
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;
}
if(p1!=null){
p.next=p1;
}
if(p2!=null){
p.next=p2;
}
return dummy.next;
}
}
递归法
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if(list1==null){
return list2;
}else if(list2==null){
return list1;
}else if(list1.val<list2.val){
list1.next=mergeTwoLists(list1.next,list2);
return list1;
}else {
list2.next=mergeTwoLists(list2.next,list1);
return list2;
}
}
}
86. 分隔链表
class Solution {
public ListNode partition(ListNode head, int x) {
ListNode dummy1=new ListNode(-1);
ListNode dummy2=new ListNode(-1);
ListNode p1=dummy1;
ListNode 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;
}
ListNode temp=p.next;
p.next=null;
p=temp;
}
p1.next=dummy2.next;
return dummy1.next;
}
}
23. 合并K个升序链表
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if (lists == null || lists.length == 0) return null;
ListNode dummy=new ListNode(-1);
ListNode p=dummy;
PriorityQueue<ListNode> pq=new PriorityQueue<>(
//lamba表达式,制定优先级队列排序规则
lists.length,(a,b)->(a.val-b.val)
);
for(ListNode head:lists){
if(head!=null){
pq.add(head);
}
}
while(!pq.isEmpty()){
ListNode node=pq.poll();
p.next=node;
if(node.next!=null){
pq.add(node.next);
}
p=p.next;
}
return dummy.next;
}
}
19. 删除链表的倒数第 N 个结点
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy=new ListNode(-1);
dummy.next=head;
ListNode fast=dummy;
ListNode slow=dummy;
for(int i=0;i<=n;i++){
fast=fast.next;
}
//记录待删除节点的闪一个节点
while(fast!=null){
fast=fast.next;
slow=slow.next;
}
slow.next=slow.next.next;
return dummy.next;
}
}
142. 环形链表 II
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast=head;
ListNode slow=head;
while(fast!=null&&fast.next!=null){
slow=slow.next;
fast=fast.next.next;
if(slow==fast){
ListNode index1=head;
ListNode index2=fast;
while(index1!=index2){
index1=index1.next;
index2=index2.next;
}
return index1;
}
}
return null;
}
}
160. 相交链表
方法一:让指针p1先遍历A,遍历完之后在遍历B;指针p2先遍历B,遍历完之后在遍历A,当p1和p2相等时,就到达了相交节点c1或者null
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode p1=headA;
ListNode p2=headB;
while(p1!=p2){
if(p1==null){
p1=headB;
}else{
p1=p1.next;
}
if(p2==null){
p2=headA;
}else{
p2=p2.next;
}
}
return p1;
}
}
方法二::
由于本题核心时让p1和p2两只真同时到达相交节点,那么可以通过预先计算两条链表的长度来解决
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lenA=0;
int lenB=0;
ListNode p=headA;
ListNode s=headB;
while(p!=null){
lenA++;
p=p.next;
}
while(s!=null){
lenB++;
s=s.next;
}
ListNode p1 = headA, p2 = headB;
if (lenA > lenB) {
for (int i = 0; i <lenA - lenB; i++) {
p1 = p1.next;
}
} else {
for (int i = 0; i <lenB - lenA; i++) {
p2 = p2.next;
}
}
// 看两个指针是否会相同,p1 == p2 时有两种情况:
// 1、要么是两条链表不相交,他俩同时⾛到尾部空指针
// 2、要么是两条链表相交,他俩⾛到两条链表的相交点
while (p1 != p2) {
p1 = p1.next;
p2 = p2.next;
}
return p1;
}
}