形与数
24. 两两交换链表中的节点
题目链接: leetcode.cn/problems/sw…
题目要求:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)
代码:
// 双指针法
class Solution {
public ListNode swapPairs(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode temp = null;
ListNode temp2 = null;
ListNode pre = new ListNode(-1, head); // 虚拟头结点
ListNode res = pre.next.next;
ListNode cur = head;
while (cur != null && cur.next != null) {
temp = pre.next;
pre.next = cur.next;
temp2 = pre.next.next;
pre.next.next = temp;
cur.next = temp2;
pre = cur;
cur = pre.next;
}
return res;
}
}
// 递归法
class Solution {
public ListNode swapPairs(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode t = head.next;
head.next = swapPairs(t.next);
t.next = head;
return t;
}
}
解题之思考及结果
这题还是建议画图比较好理解,因为指针指来指去的不画图容易晕乎。
双指针法:定义一个pre节点作为虚拟头结点,pre指针指向上一个节点,cur指向当前节点,方便操作。期间需要用temp1和temp2两个指针来暂存操作时的指针防止丢失,其他就是模拟循环过程了。
递归法:附上一个解读递归比较好的文章lyl0724.github.io/2020/01/25/…
19. 删除链表的倒数第N个节点
题目要求:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
代码:
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode f = head;
ListNode l = head;
ListNode pre = new ListNode(-1, head);
ListNode res = pre;
int index = 1;
// 先知道链表长度,再根据链表长度删除对应节点
while (l.next != null) {
l = l.next;
index++;
}
while ((n - (index--)) != 0) {
pre = f;
f = f.next;
}
pre.next = f.next;
return res.next;
}
}
解题之思考及结果
这题我用的是挺普通的解法,先求得链表的长度,然后再让头指针走 (n - index-- == 0) 步即到达待删节点的前一节点。
160. 链表相交
题目要求:给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
代码:
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode a = headA;
ListNode b = headB;
while (a != b) {
a = a != null ? a.next : headB;
b = b != null ? b.next : headA;
}
return a;
}
}
解题之思考及结果
阅读了Krahets大神的代码,惊叹于代码之美。此题核心在于两链表A、B走的路会有一个重合点,设链表重合部分为C,则有A+C+B = B+C+A 。那么只要headA和headB走完自己的路再走别人的路,不断重复,那么总会重合
142.环形链表II
题目链接: leetcode.cn/problems/li…
题目要求:给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表
代码:
public class Solution {
public ListNode detectCycle(ListNode head) {
if (head == null || head.next == null) {
return null;
}
ListNode fast = head;
ListNode slow = head;
// 判断有没有环,有环必定相遇
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
// 查找入环点
if (fast == slow) {
ListNode index1 = head;
ListNode index2 = fast;
while (index1 != index2) {
index1 = index1.next;
index2 = index2.next;
}
return index1;
}
}
return null;
}
}
解题之思考及结果
此题要解决的问题有二:
一为如何判断有环;
二为如果有环该怎么找到入环点。
解决问题一很简单,我们只需要定义快慢指针,快指针每次走两步,慢指针每次走一步。那么如果有环,他们总会相遇。既然相遇了那么怎么找到入环点。这里我推荐Carl兄的视频,因为这视频里数学或是逻辑上都不错。
把环形链表讲清楚! 如何判断环形链表?如何找到环形链表的入口? LeetCode:142.环形链表II