两两交换链表中的节点
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
解题的关键在于需要理解清楚循环退出的条件,同时处理好每个循环中节点交换的逻辑,建议先在草稿本上画出交换的逻辑。
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummyHead = new ListNode(-1, head);
ListNode current = dummyHead;
while(current.next != null && current.next.next != null) {
ListNode temp1 = current.next; // 保存节点到临时变量中
ListNode temp2 = current.next.next.next; // 保存节点到临时变量中
current.next = current.next.next;
current.next.next = temp1;
current.next.next.next = temp2;
current = current.next.next;
}
return dummyHead.next;
}
}
删除链表的倒数第N个节点
给你一个链表,删除链表的倒数第
n个结点,并且返回链表的头结点。
经典的快慢指针的问题,快指针走到终点的时候,慢指针刚好走到倒数第n个节点的前一个节点,方便进行节点的操作。注意也是需要设置一个dummyHead来处理原始链表的头节点。
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode faster = head;
ListNode dummyHead = new ListNode(-1, head);
ListNode slower = dummyHead;
int counter = 1;
ListNode result = slower;
while(faster != null) {
if(counter < n) {
counter++;
} else {
if(faster.next == null) {
slower.next = slower.next.next;
break;
}
slower = slower.next;
}
faster = faster.next;
}
return result.next;
}
}
面试题 02.07. 链表相交
引入了一个hashSet来解决判断是否相等的问题,好处是比较容易想到,坏处是占用了一定的内存空间
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode currentA = headA;
ListNode currentB = headB;
ListNode result = null;
HashSet<ListNode> set = new HashSet<>();
while(currentA != null) {
set.add(currentA);
currentA = currentA.next;
}
while(currentB != null) {
if(set.contains(currentB)) {
result = currentB;
break;
} else {
currentB = currentB.next;
}
}
return result;
}
}
142.环形链表II
引入hashset这题会非常容易,如果不能引入额外的空间,就需要用其指针的方法来解决。
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode current = head;
Set<ListNode> set = new HashSet<>();
ListNode result = null;
while(current != null) {
if(set.contains(current.next)) {
result = current.next;
break;
} else {
set.add(current);
}
current = current.next;
}
return result;
}
}
链表总结
链表相关的问题在写代码的时候往往并不容易,很多时候虽然知道思路,但是在实现的时候会出现很多问题。在实现的时候需要注意:
- 头节点的处理
- 循环中引用的处理,不能随意修改一个引用的指向
- 想清楚退出条件
- 注意看题目要求返回的是特殊节点还说头节点,如果是头节点,相当于就是返回处理好之后的整个链表
- 对于需要遍历所有元素,然后处理倒数数字的问题,可以考虑快慢指针
- 任何链表相关的问题最好先画出来,理清思路,再开始写代码