LeetCode19.删除链表的倒数第n个节点
这道题还是双指针的经典应用。如果要删除倒数第n个结点,让 fast 指针先移动 n 步,然后再让 slow 指针移动,这样在 fast 指针到达链表的尾部时候,就可以删除slow所指向的结点了。
但是思路是如此,实际的编码过程还有很多细节。
比如:我们在链表中删除删除节点,我们需要知道他的前驱结点,然后才能完成删除。所以在这里我们让 fast 先移动 n + 1 步,这样 slow 就指向了 要删除节点的前一个节点,方便我们操作。
代码如下:
public ListNode removeNthFromEnd(ListNode head, int n) {
//定义虚拟头结点
ListNode dummyHead = new ListNode(head, -1);
//定义快慢指针
ListNode fastNode = dummyHead;
ListNode slowNode = dummyHead;
//只要让快慢指针相差 n 个结点即可
for (int i = 0; i < n + 1; i++) {
fastNode = fastNode.next;
}
//在fast指针到达链表的尾部时,slow指针最终指向要删除节点的前一个节点
while (fastNode != null) {
fastNode = fastNode.next;
slowNode = slowNode.next;
}
//完成删除操作,让前一个节点指向前一个节点的下一个节点的下一个节点。
slowNode.next = slowNode.next.next;
return dummyHead.next;
}
LeetCode面试题0207.链表相交
本题求的是两个链表交点节点的指针,要注意:我们要的是指针相等,而不是数值相等。
本题思路还是很简单的,我们需要只需要让两个链表的长度一致,然后一个一个的比较指针是否相等即可。如果相同就返回,如果不相同,就返回空。
代码如下:
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode pointA = headA;
ListNode pointB = headB;
int lenA = 0;
int lenB = 0;
//求链表A的长度
while (pointA != null) {
lenA++;
pointA = pointA.next;
}
//求链表B的长度
while (pointB != null) {
lenB++;
pointB = pointB.next;
}
//重置一下子
pointA = headA;
pointB = headB;
//让pointA成为最长链表的头,LenA为其长度
if (lenB > lenA) {
int tempLen = lenA;
lenA = lenB;
lenB = tempLen;
//swap(pointA,pointB)
ListNode tempNode = pointA;
pointA = pointB;
pointB = tempNode;
}
//求长度差
int gap = lenA - lenB;
//让pointA和 pointB 在同一起点上 (末尾位置对齐)
while (gap-- > 0) {
pointA = pointA.next;
}
//遍历pointA和pointB遇到相同则返回
while (pointA != null) {
if (pointA == pointB) {
return pointA;
}
pointA = pointA.next;
pointB = pointB.next;
}
return null;
}
LeetCode24.两两交换链表中的节点
初始时,cur指向虚拟头结点,然后进行如下三步:
操作之后,链表如下:
看这个可能就更直观一些了:
代码如下:
public ListNode swapPairs(ListNode head) {
//定义虚拟头结点
ListNode dummyHead = new ListNode(head, -1);
//定义用于遍历的指针
ListNode point = dummyHead;
//定义三个用于保存的指针
ListNode temp = null;
//保存第一个结点的指针
ListNode firstPoint = null;
//保存第二个节点的指针
ListNode secondPoint = null;
while (point.next != null && point.next.next != null) {
//保存指针的下一个节点的下一个节点的下一个节点
temp = point.next.next.next;
firstPoint = point.next;
secondPoint = point.next.next;
point.next = secondPoint;
secondPoint.next = firstPoint;
firstPoint.next = temp;
//将point向后移动,准备下一轮的交换
point = firstPoint;
}
return dummyHead.next;
}
LeetCode142.环形链表II
代码如下:
public ListNode detectCycle(ListNode head) {
//定义快慢指针
//快指针一次走两步
ListNode fastPoint = head;
//慢指针一次走一步
ListNode slowPoint = head;
while (fastPoint != null && fastPoint.next != null) {
fastPoint = fastPoint.next.next;
slowPoint = slowPoint.next;
//相遇了标识有环
if (fastPoint == slowPoint) {
//这时我们要找到环的入口
ListNode index1 = head;
ListNode index2 = fastPoint;
while (index1 != index2) {
index1 = index1.next;
index2 = index2.next;
}
return index1;
}
}
return null;
}