重点:
leetcode24:
- 涉及到头节点变化的操作时,一定要创建一个虚拟头结点来指向新的头节点。
- 最好不要让指针处于要交换的结点的状态
leetcode19:
- 进阶方法可以用双指针,前一个指针与后一个指针一直保持着n的距离,则可以实现一趟扫描便可删除。
leetcode160:
- 核心方法为:消除两个链表的长度差。
LeetCode24. 两两交换链表中的节点
public ListNode swapPairs(ListNode head) {
//处理只有1个结点和没有结点的情况
if(head==null||head.next==null) {
return head;
}
//虚拟头结点
ListNode dmm =new ListNode(0);
dmm.next=head;
// 初始化指针
ListNode current = dmm;
//当交换的第二个结点不为空时
while(current.next!=null&¤t.next.next!=null) {
//交换结点
ListNode temp = current.next.next;
current.next.next=current.next.next.next;
temp.next=current.next;
//还要考虑前一个结点到这个结点之间的连接问题
current.next=temp;
//向前
current=current.next.next;
}
//head指针可能变了位置,所以应该返回虚拟头结点
return dmm.next;
}
LeetCode19.删除链表的倒数第N个节点
public ListNode removeNthFromEnd(ListNode head, int n) {
//排除特殊情况
if(head==null) {
return head;
}
//创建虚结点
ListNode dmm = new ListNode(0);
dmm.next=head;
ListNode p = dmm;
//记录一共有多少个结点
int num=0;
//遍历到最后一个结点
while(p.next!=null) {
num++;
p=p.next;
}
//记录一共要走几步
int step = num-n;
p = dmm;
while(step>0) {
p=p.next;
step--;
}
//删除结点
p.next=p.next.next;
return dmm.next;
}
LeetCode160.相交链表
/**
* 核心:消除两个链表的长度差
* @param headA
* @param headB
* @return
*/
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) return null;
ListNode pA = headA, pB = headB;
while (pA != pB) {
pA = pA == null ? headB : pA.next;
pB = pB == null ? headA : pB.next;
}
return pA;
}
LeetCode142.环形链表II
public ListNode detectCycle(ListNode head) {
Set<ListNode> set = new HashSet<>();
while(head!=null) {
if(!set.contains(head)) {
set.add(head);
}else {
return head;
}
head=head.next;
}
return null;
}