两两交换链表中的节点
题目描述:
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
我的解题思路:
首先定义一个虚拟头结点,便于统一对节点的操作。
ListNode virtualHead = new ListNode(0);
virtualHead.next = head;
要实现两个节点的交换,我需要创建两个节点,用来帮我实现交换。(不用纠结为什么叫slowNode, fastNode)
ListNode slowNode, fastNode;
我们第一步创建的virtualHead
是不参与中间过程的,所以还需要创建一个节点,用来在链表中移动。
ListNode cur = virtualHead;
接下来就是两两交换节点的过程
在交换两个节点的位置之前,一定要保存第三个节点,不然他就丢失了。
ListNode temp = cur.next.next.next;
交换两个节点的方法很简单,就是改变他的next域。
slowNode = cur.next;
fastNode = cur.next.next;
fastNode.next = slowNode;
slowNode.next = temp;
交换完两个节点之后,我们需要修改cur的next域,以及重新赋值cur节点。
cur.next = fastNode;
cur = slowNode;
接下来就是循环上面的过程,那么循环的条件是什么呢?
cur指向的是待交换的节点的前一个位置。如果他的后两个节点存在,那么就需要进入循环;如果不足两个节点,那么就不喜欢交换节点,也就不需要进入循环。可知,循环条件是
while(cur.next != null && cur.next.next!= null)
交换完之后,就返回头节点。注意头结点不是head
,经过交换后,head
已经是第二个节点了。头结点是virtualHead.next
。
所以返回语句是
return virtualHead.next;
完整代码如下:
public ListNode swapPairs(ListNode head) {
ListNode virtualHead = new ListNode(0);
virtualHead.next = head;
ListNode slowNode,ListNode fastNode;
ListNode cur = virtualHead;
while(cur.next != null && cur.next.next!= null){
ListNode temp = cur.next.next.next;
slowNode = cur.next;
fastNode = cur.next.next;
fastNode.next = slowNode;
slowNode.next = temp;
cur.next = fastNode;
cur = slowNode;
}
return virtualHead.next;
}
删除链表的倒数第N个节点
题目描述:
给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
我的解题思路:
这道题比较简单,看到倒数n个节点,就能想到可以用快慢指针的方法,两个指针之间相差n个位置。当快指针的next
域为空的时候,慢指针的next
域就是要删除的节点。这个知识点记住就行。
首先是常规步骤,定义一个虚拟头结点。
ListNode virtualHead = new ListNode(0);
virtualHead.next = head;
然后定义快慢指针
ListNode slow = virtualHead;
ListNode fast = virtualHead;
接着让快指针移动n步
for(int i = 0; i < n;i++){
fast = fast.next;
}
然后同时移动快慢指针,让快指针的next
域为空
while(fast.next != null){
slow = slow.next;
fast = fast.next;
}
然后是删除指定节点
slow.next = slow.next.next;
完整代码如下:
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode virtualHead = new ListNode(0);
virtualHead.next = head;
ListNode slow = virtualHead;
ListNode fast = virtualHead;
for(int i = 0; i < n;i++){
fast = fast.next;
}
while(fast.next != null){
slow = slow.next;
fast = fast.next;
}
slow.next = slow.next.next;
return virtualHead.next;
}
链表相交
题目描述:
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null
。
我的解题思路:
如果链表相交的话,说明,节点是一样的。那么我们就可以用==
来判断两个链表的节点是否一样。
但是这两个链表的长度不一定是相同的,于是我们就要先求出这两个链表的长度。求链表的长度很简单,直接遍历就好了。
int lenA = 0, lenB = 0;
ListNode temp = headA;
while (temp != null) {
lenA++;
temp = temp.next;
}
temp = headB;
while (temp != null) {
lenB++;
temp = temp.next;
}
现在我们知道了这两个链表的长度。为了对齐链表的节点,我们需要移动其中一个链表。我们假设链表A更长,如果链表A的长度比链表B短,那么我们就交换这两个链表。
if(lenB > lenA){
temp = headB;
headB = headA;
headA = temp;
int temp2 = lenB;
lenB = lenA;
lenA =temp2;
// 犯了一个错。下面两行在第一次提交代码的时候没有写。
// 交换完链表A跟链表B后,相应的虚拟头节点也要做修改
virtualHeadA.next = headA;
virtualHeadB.next = headB;
}
为啥要做交换链表这个操作,我不交换可以吗?
答案是当然可以。但是下面这段移动链表A的位置的代码就不能直接这样写了
ListNode curA = virtualHeadA;
for(int i = 0; i < count;i++){
curA = curA.next;
}
因为如果链表B更长的话,这里移动的应该是链表B。我加了交换链表的逻辑后,移动链表的代码就可以统一写成链表A了。
最后是判断两个链表的节点是否是相同的节点。这一段逻辑很简单。
while(curA != null && curB != null){
if(curA == curB){
return curA;
}else{
curA = curA.next;
curB = curB.next;
}
}
完整代码如下:
public static ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lenA = 0, lenB = 0;
ListNode temp = headA;
ListNode virtualHeadA = new ListNode(0);
ListNode virtualHeadB = new ListNode(0);
virtualHeadA.next = headA;
virtualHeadB.next = headB;
while (temp != null) {
lenA++;
temp = temp.next;
}
temp = headB;
while (temp != null) {
lenB++;
temp = temp.next;
}
//交换过后,a是长的,b是短的
if(lenB > lenA){
temp = headB;
headB = headA;
headA = temp;
int temp2 = lenB;
lenB = lenA;
lenA =temp2;
// 犯了一个错。下面两行在第一次提交代码的时候没有写。
// 交换完链表A跟链表B后,相应的虚拟头节点也要做修改
virtualHeadA.next = headA;
virtualHeadB.next = headB;
}
int count = lenA-lenB;
ListNode curA = virtualHeadA;
for(int i = 0; i < count;i++){
curA = curA.next;
}
//此时链表a跟链表b的剩余个数是一样的
ListNode curB = virtualHeadB;
while(curA != null && curB != null){
if(curA == curB){
return curA;
}else{
curA = curA.next;
curB = curB.next;
}
}
return null;
环形链表2
题目描述:
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null
。
我的解题思路:
未完待续…
参考链接:
代码随想录-链表-5.两两交换链表中的节点
代码随想录-链表-6.删除链表的倒数第N个节点
代码随想录-链表-7.链表相交
代码随想录-链表-8.环形链表