DAY4 24.两两交换链表中的节点 19.删除链表的倒数第n个节点 02.07. 链表相交 142.环形链表
24、两两交换链表中的节点
题目链接
思路
本题刚开始看到没有什么思路,后来学习了代码随想录的讲解,同样应该使用双指针的解法。主要分为以下几个步骤:
代码随想录讲解
1、先定义一个虚拟头节点,并添加一个pre指针指向虚拟头节点,步骤一先使得pre.next指向head的下一个节点。
2、使得head.next.next指向head,也就是从2指向1。
3、从1指向3,但是这时候出现了一个问题,3号节点的地址已经丢失,无法连接,所以我们要提前对3号节点的地址进行存储。
代码实现
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummyNode = new ListNode(-1,head);
ListNode pre = dummyNode;
while(pre.next != null && pre.next.next != null){
ListNode tmp = head.next.next;
pre.next = head.next;
head.next.next=head;
head.next=tmp;
pre = head;
head=head.next;
}
return dummyNode.next;
}
}
19、删除链表的倒数第n个节点
题目链接
思路
本题使用的也是快慢指针的思路,删除倒数第n个节点,就需要让快指针移动n步,然后再和慢指针一起移动,慢指针即指向待删除节点的前一个节点,将该节点删除即可。
代码实现
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummyNode = new ListNode(-1,head);
ListNode fastIndex = dummyNode;
ListNode slowIndex = dummyNode;
for(int i = 0;i < n;i++){
fastIndex = fastIndex.next;
}
while(fastIndex.next != null){
slowIndex = slowIndex.next;
fastIndex = fastIndex.next;
}
slowIndex.next = slowIndex.next.next;
return dummyNode.next;
}
}
面试题 02.07、链表相交
题目链接
思路
分别在两条链表上定义两个指针curA和curB,循环遍历求出两个链表的长度。让A代表较长的那条链表,并使得两条链表从尾部对齐。这时候让两条链表同时往后走,直到找到地址相同的节点返回,如果没有,则返回null。
代码实现
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode curA = headA;
ListNode curB = headB;
int lenA = 0;
int lenB = 0;
while(curA != null){
lenA++;
curA = curA.next;
}
while(curB != null){
lenB++;
curB = curB.next;
}
curA = headA;
curB = headB;
if(lenB > lenA){
int tmpLen = lenA;
lenA = lenB;
lenB = tmpLen;
ListNode tmpNode = curA;
curA = curB;
curB = tmpNode;
}
int gap = lenA - lenB;
while(gap-- > 0){
curA = curA.next;
}
while(curA != null){
if(curA == curB){
return curA;
}
curA = curA.next;
curB = curB.next;
}
return null;
}
}
142、环形链表
题目链接
思路
最开始看到本题,没有任何思路,后来学习了代码随想录的解题方法。
代码随想录题解
本题的解题思路还是快慢指针,初始让快慢指针同时指向头节点,向链表后遍历,慢指针每次走一步,快指针每次走两步,快指针一定会在环内和慢指针相遇。当两个指针相遇时,环入口距离头节点为x,已走过相遇点距离为y,距离下一圈入口为z,相遇时,快指针走过的节点是慢指针的2倍,(x+y)*2 = n(y+z),两边同时去掉一个x+y,x = (n - 1) (y + z) + z,当n=1时,x=z,所以如果一个指针从head到环入口,和从相遇点到环入口是相等的,定义两个指针,使他们每次同时前进一步,最终的相遇点即为环的入口。
代码实现
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fastIndex = head;
ListNode slowIndex = head;
while(fastIndex != null && fastIndex.next !=null){
slowIndex = slowIndex.next;
fastIndex = fastIndex.next.next;
if(fastIndex == slowIndex){
ListNode index1 = fastIndex;
ListNode index2 = head;
while(index1 != index2){
index1 = index1.next;
index2 = index2.next;
}
return index1;
}
}
return null;
}
}