一、24.两两交换链表中的节点
学习链接:两两交换链表中的节点
状态:做出来了
细节之处:1 2 3(代码里面)
思路:使用虚拟头节点,找到要交换的俩个链表节点前一个位置记为cur,使用temp保存cur,temp1保存下一个cur即cur.next.next.next.然后执行三个步骤如代码所示。
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummy=new ListNode();
dummy.next=head;
ListNode cur=dummy;
while(cur.next!=null&&cur.next.next!=null) //1 必须先写cur.next,如果先cur.next.next,cur.next为空的话,会造成空指针异常
{
ListNode temp=cur.next;
ListNode temp1=cur.next.next.next;
cur.next=cur.next.next; //2 顺序很重要,这个在这代码必须在第一个,因为cur.next.next没保存
cur.next.next=temp;
temp.next=temp1;
cur=cur.next.next; //3 移动到下一个cur
}
return dummy.next;
}
}
二、19.删除链表的倒数第N个节点
学习链接:删除链表的倒数第N个节点
状态:做出来了
细节之处:1 2 3(代码里面)
思路:只需让慢指针和快指针一直保持n+1的距离,这样快指针到到达终点后,慢指针恰好在删除元素的前一个节点。
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy=new ListNode();
dummy.next=head;
ListNode cur=dummy.next;
int stride=0; //1 快慢节点的距离
ListNode slow=dummy;
while(cur!=null)
{
cur=cur.next;
stride++;
if(stride>=n+1){slow=slow.next;} //2 保持快慢节点的距离在n+1,使得slow为要删除的前一个节点
}
if(slow.next!=null) //3 防止链表只有一个元素来报出空指针异常
{slow.next=slow.next.next;}
return dummy.next;
}
}
三、160.链表相交
学习链接:链表相交
状态:做出来了
细节之处:1 2 3(代码里面)
思路:因为这道题是链表,由于相交的部分肯定是在尾部往前,并且如果相交,俩链表的尾部一定是相同的,所以不需要俩层循环,直接对其尾部一个一个比较即可。
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; //1 算出长度之后一定要回到原来状态
curB = headB;
if (lenA < lenB) { //2 使得A一直是俩链表中最长的一个,减少后面代码的冗余
int templen = lenB;
lenB = lenA;
lenA = templen;
ListNode temp = curB;
curB = curA;
curA = temp;
}
int gap = lenA - lenB;
while (gap-- > 0) {
curA = curA.next;
}
while (curB != null) { //3 因为这道题目的特殊性,公共部分一定在末尾
if (curA == curB) return curA;
curA = curA.next;
curB = curB.next;
}
return null;
}
}
四、142.环形链表II
学习链接:环形链表II
状态:没做出来
细节之处:1 2 3(代码里面)
思路:这道题需要数学证明,所以放截图了(代码随想录里面的)。
证明有环:
证明环的入口:
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) { //1 只需要防止fast空指针异常,因为fast比slow快
slow=slow.next;
fast=fast.next.next;
while(slow==fast) //2 已经判断出来有环了
{
ListNode first=head;
ListNode second=slow;
while(second!=first) //3 相遇的地方就是入口处,上面有证明
{
first=first.next;
second=second.next;
}
return first;
}
}
return null;
}
}
五、 总结
学了虚拟头节点(在增删改的时候,不需要特殊处理头节点),也懂得了链表的基本操作和利用链表解决算法问题。本人经常出错的点在空指针异常(首节点为空造成的),还有一些cur(当前节点)为了一些目的进行的操作,最后cur没有回到之前的位置,造出错误,这些需要特别注意。