24.两两交换链表中的节点
思路:
分三步进行
两两一组(首先记录一下下一组第一个节点temp)
1、每一组前面需要连接的节点pre(第一组设置为虚拟头结点)连head.next
2、head.next连head
3、head连最开始记录的下一组的第一个节点head.next.next
代码:
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode pre = dummy;
while(pre.next != null && pre.next.next != null){
//记录下一组的头
ListNode temp = head.next.next;
//分三步连接
pre.next = head.next;
head.next.next = head;
head.next = temp;
pre = head;
head = head.next;
}
return dummy.next;
}
}
需要注意的点:
1、涉及到头结点改变的操作需要设置虚拟头结点。
2、在两两交换前需要标记下一组的第一个节点,防止释放。
3、循环要在pre后存在可交换的两个节点才可进行。
4、返回值为虚拟头结点的下一个。
19.删除链表的倒数第N个节点
思路:
快慢指针,快指针先走n+1步(这个由循环条件决定),然后快慢指针一起走,当快指针为空时,慢指针的下一个节点为需要删除的节点。
代码:
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//可能删除头结点,所以要设置虚拟头结点
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode slow = dummy;
ListNode fast = dummy;
//快慢指针相差n
for(int i = n; i > -1; i--){
fast = fast.next;
}
while(fast != null){
slow = slow.next;
fast = fast.next;
}
slow.next = slow.next.next;
return dummy.next;
}
}
需要注意的点:
1、涉及到(可能存在)头结点的改变,需要设置虚拟头结点。
2、快指针向前走多少步或者终止指针判定分不清时,可以举例子验证。
面试题 02.07. 链表相交
思路:
两链表相交(若有),交点后的节点数一样,交点前的节点数和两链表的长度有关。
先遍历两链表,记录其长度,让较长的链表用开头用指针标记前进长度差值步,然后一起前进至链表结束,看是否存在相同节点。
代码:
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lenA = 0;
int lenB = 0;
ListNode a = headA;
ListNode b = headB;
while(a != null){
a = a.next;
lenA++;
}
while(b != null){
b = b.next;
lenB++;
}
int gap = (lenA - lenB) > 0 ? lenA - lenB : lenB - lenA;
//a为较长链的头结点
if(lenA - lenB > 0){
a = headA;
b = headB;
}else{
b = headA;
a = headB;
}
for(int i = 0; i < gap; i++){
a = a.next;
}
while(a != null){
if(a == b){
return a;
}
a = a.next;
b = b.next;
}
return null;
}
}
需要注意的点:
1、两链表长度的差值可能为负数,注意保证其非负和辨认较长链表。
142.环形链表II
思路:
快慢指针:慢指针走一步,快指针走两步(循环控制要用快指针,因为走的快,如果无环先遇到空,直接返回null),若有环则两指针相遇,两环相遇时慢指针回到起点,两指针一起向前走,直到遇到相同的节点,即为环形链表入口节点。证明见代码随想录网站。
代码:
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
if(slow == fast){//有环
slow = head;
while(slow != fast){
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
return null;
}
}
需要注意的点:
1、循环用fast来控制,具体判断向前几步为空都行 。