24. 两两交换链表中的节点
力扣题目链接
基本思路
- 迭代,注意指针模拟操作,定义虚拟头节点用来指向链表
- 递归
迭代
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummy = new ListNode(0, head); // 用哨兵节点简化代码逻辑
ListNode node0 = dummy;
ListNode node1 = head;
while (node1 != null && node1.next != null) { // 至少有两个节点
ListNode node2 = node1.next;
ListNode node3 = node2.next;
node0.next = node2; // 0 -> 2
node2.next = node1; // 2 -> 1
node1.next = node3; // 1 -> 3
node0 = node1; // 下一轮交换,0 是 1
node1 = node3; // 下一轮交换,1 是 3
}
return dummy.next; // 返回新链表的头节点
}
}
递归
class Solution {
public ListNode swapPairs(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode node1 = head;
ListNode node2 = head.next;
ListNode node3 = node2.next;
node1.next = swapPairs(node3); // 1 指向递归返回的链表头
node2.next = node1; // 2 指向 1
return node2; // 返回交换后的链表头节点
}
}
- 时间复杂度:O(n),其中 n 为链表长度。
- 空间复杂度:O(n)。递归需要 O(n) 的栈空间。
19.删除链表的倒数第N个节点
力扣题目链接
基本思路
- 快慢指针,两个指针间隔n-1节点,当快指针到最后节点时,满指针刚好指向倒数第n个节点的前一个节点
方法代码
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0, head);
ListNode fast = dummy;
ListNode slow = dummy;
while(n > 0){
//这里快指针先移动n步,所以下面的判断是fast.next != null
fast = fast.next;
n--;
}
while(fast.next != null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummy.next;
}
}
面试题 02.07. 链表相交
力扣题目链接
基本思路
- 求出两个链表的长度,让两个指针指向短的链表长度的位置,之后同时遍历两个链表,若有指向相同的位置,则相交
方法代码
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lenA = 0;
int lenB = 0;
ListNode pA = headA;
ListNode pB = headB;
while(pA != null){
lenA++;
pA = pA.next;
}
while(pB != null){
lenB++;
pB = pB.next;
}
pA = headA;
pB = headB;
//让A为长的那个
if(lenA < lenB){
int temp = lenA;
lenA = lenB;
lenB = temp;
ListNode tempNode = pA;
pA = pB;
pB = tempNode;
}
int d = lenA - lenB;
while(d > 0){
pA = pA.next;
d--;
}
while(pA != null){
if(pA == pB){
return pA;
}
pA = pA.next;
pB = pB.next;
}
return null;
}
}
142. 环形链表 II
力扣题目链接
基本思路
- 见代码随想录
方法代码
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast = head;
ListNode slow = head;
ListNode meetNode;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
//先判断是否有环
if (fast == slow) {
//分别从相遇节点和头节点开始遍历
meetNode = fast;
ListNode p = head;
while (p != meetNode) {
p = p.next;
meetNode = meetNode.next;
}
return p;
}
}
return null;
}
}
- 时间复杂度:O(n),快慢指针相遇前,指针走的次数小于链表长度,快慢指针相遇后,两个index指针走的次数也小于链表长度,总体为走的次数小于 2n
- 空间复杂度:O(1)