一、两两交换链表中的节点
这道题主要是设置一个虚拟头节点ListNode dummyhead = new ListNode(-1);之后再创建一个指向虚拟头结点的指针cur,再将虚拟头结点和头节点连起来cur.next = head;之后创建一个临时指针(指向第三个节点),还有指向第一个节点的指针,指向第二个节点的指针
再进行while循环,循环条件是不能是没有节点并且不能是一个节点(cur.next!=null && cur.next.next!=null)
之后就是循环,将创建的指针分别指向虚拟指针之后的对应 第一、第二、第三个节点,这都是用cur.next表示的,为的是每次最后移动cur到下一轮的时候,这三个指针也会自动移动到下一轮的位置,因为是都是基于cur.next来创建的
然后就是节点的断链和重新指向的赋值(三步),之后将cur指向最后交换的位置firstNode,继续做下一轮的交换,
最后循环结束,返回新的头节点,也就是之前创建的虚拟头节点的next:dummy.next
代码如下:
/**
* 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 dummyhead = new ListNode(-1);
ListNode cur = dummyhead;
dummyhead.next = head;
ListNode temp;
ListNode firstNode;
ListNode secondNode;
while(cur.next!=null && cur.next.next!=null )
{
firstNode = cur.next;
secondNode = cur.next.next;
temp = cur.next.next.next;
cur.next = secondNode;
secondNode.next = firstNode;
firstNode.next = temp;
cur = firstNode;
}
return dummyhead.next;
}
}
二、删除链表的倒数第N个节点
这道题主要是考察一个虚拟头节点还有双指针的应用,先定义一个虚拟头节点还有两个快慢指针,虚拟头节点的next指向头节点,两个指针都指向虚拟头节点
明白题目给定的n和咱们快慢指针的移动的关系,首先先让快指针移动n+1步【因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便做删除操作)】 因为这样快慢指针中间的距离会控制在n,在之后快慢指针一起向后移动的时候,那么在快指针指向最后null位置的时候,慢指针与快指针之间的距离是n所以慢指针指向的位置就是倒数第n个位置,这时你会发现慢指针的next即为待删的倒数第n个节点,之后直接进行节点删除的正常操作。
代码如下:
/**
* 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 removeNthFromEnd(ListNode head, int n) {
ListNode virtue = new ListNode(-1);
ListNode fast;
ListNode slow;
virtue.next = head;
fast = virtue;
slow = virtue;
for(int i = 0;i<n+1;i++)
{
fast = fast.next;
}
while(fast != null)
{
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return virtue.next;
}
}
三、面试题-链表相交

首先这道题主要是找到规律,题目给定的都是在相交节点之后,a和b两个链表的数值都相同
所以先把两链表的尾巴对齐,然后要让a链表的头结点指针先移动lena-lenb的长度,这时就要求出a、b两个链表的长度,这里用while循环,但是最后出了循环别忘了,nodea和nodeb要同时再指回原来的a、b头结点指针
移动lena-lenb的长度后,这时a的结点指针与b的头结点指针对齐了,之后两指针同时向后移动,如果a和b的指针相同,那么代表这个位置是交点,返回nodea(或nodeb),否则返回的是空null【考虑的情况都是lena>lenb的情况,所以中间还要做一个lenb>lena的转换,将a的长度移动到b的长度,将a的头结点指针移动到b的头结点指针处,反之,将b的值和头结点指针都移动到a的地方,这样处理完之后还是相当于是lena>lenb】
代码如下:
/**
* 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 nodea = headA;
ListNode nodeb = headB;
int lena = 0;
int lenb = 0;
while(nodea != null)
{
lena++;
nodea = nodea.next;
}
while(nodeb != null)
{
lenb++;
nodeb = nodeb.next;
}
nodea = headA;
nodeb = headB;
if(lenb > lena)
{
int tempt = lena;
lena = lenb;
lenb = tempt;
ListNode temp = nodea;
nodea = nodeb;
nodeb = temp;
}
int gep = lena - lenb;
while(gep-- > 0)
{
nodea = nodea.next;
}
while(nodea != null)
{
if(nodea == nodeb)
{
return nodea;
}
nodea = nodea.next;
nodeb = nodeb.next;
}
return null;
}
}
四、环形链表II
这道题首先要明白,设置双指针,一快一慢,快指针走两个节点 ,慢指针走一个节点,如果有环的话一定会有相遇点
找到相遇点后,我们需要推出来,从头出发和从相遇点出发,这次是每个指针都是走的一个节点,之后相遇的点就是环的入口,这里需要简单的推导一下
假设从头结点到环形入口节点 的节点数为x。 环形入口节点到 fast指针与slow指针相遇节点 节点数为y。 从相遇节点 再到环形入口节点节点数为 z。 如图所示:
之后就是在第一次相遇后,为什么要写if(fast != null&& fast.next != null)?
答:为什么需要判断 fast != null
呢?这是因为当快指针(fast
)在遍历链表时,如果它能够成功遍历到链表的末尾,那么说明链表没有环。因此,循环的终止条件是 fast != null
之后在if条件里再while头部指针和相遇节点再次移动一个节点,找到相等时即是环的入口
最后如果第一个while之后还没有找到环入口,那么就是返回的是null(题上的条件)
这道题要注意的点有两个:首先要定义快慢指针都从头节点开始,每次快指针向后移动两个单位,慢指针向后移动一个单位,如果有环的话他们一定会相遇的,这是一个定理,之后在相遇的时候又定义了一个头节点开始的指针,一个相遇点的指针,然后两个一起向后移动,如果能相遇的话,说明这是环的入口,这个也是一个定理,是推导出来的,不管那个相遇点转几圈,他都会和从头开始的指针在环的入口相见
代码如下:
/**
* 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 fast;
ListNode slow;
fast = head;
slow = head;
while(fast.next != null&&fast.next.next != null)
{
slow = slow.next;
fast = fast.next.next;
if(fast == slow)
{
ListNode index1 = head;
ListNode index2 = fast;
while(index1 != index2)
{
index1 = index1.next;
index2 = index2.next;
}
return index2;
}
}
return null;
}
}