代码随想录训练营第四天|LeetCode24两两交换链表的结点,LeetCode19.删除链表的倒数第N个节点,LeetCode160链表香蕉,LeetCode142环形链表1,LeetCode142环形链表2
题目链接24两两交换链表的结点
思路:主要搞清楚三个问题,第一是两个结点交换时操作指针一定指向第一个结点的前一个结点,第二是遍历的终止条件是什么,第三是两个结点交换的实现逻辑。
代码如下:
public ListNode swapPairs(ListNode head) {
ListNode s = new ListNode(-1,head);//定义一个哨兵结点并指向头结点
ListNode curr = s;//定义指针指向哨兵结点
while(curr.next != null && curr.next.next != null){//奇数个和偶数个都适用且不能颠倒顺序
ListNode temp = curr.next;//哨兵结点断开了所以得保存第一个结点的指针
ListNode temp1 = curr.next.next.next;//第二个结点断开所以保存第三个结点的指针
curr.next = curr.next.next;//第一次是哨兵结点指向第二个结点
curr.next.next = temp;
curr.next.next.next = temp1;
curr = curr.next.next;
}
return s.next;
}
题目链接19删除链表的倒数第N个结点
思路:删除倒数第n个结点前一定得找到其前一个结点,用双指针法快慢指针首先都指向哨兵结点,然后快指针先走n+1步,然后再快慢指针同时走,然后找到了删除。
代码如下:
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode s = new ListNode(-1,head);
ListNode fast = s;
ListNode slow = s;
//快指针先走n+1步
for(int i = 0; i <= n; i++){
fast = fast.next;
}
//快慢指针同时走
while(fast != null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return s.next;
}
题目链接160链表相交
思路:搞清楚链表相交的结点一定是操作指针都指向它并且是第一次,所以两个链表长度不一样的话遍历速度也有所不同,于是可以求出两个链表长度的差值,然后将两个链表尾部对齐,让两个链表从同一起始位置遍历即可。
代码如下:
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode curA = headA, curB = headB;
int lenA = 0, lenB = 0;
while(curA != null){
lenA++;
curA = curA.next;
}
while(curB != null){
lenB++;
curB = curB.next;
}
curA = headA;
curB = headB;
//规范链表A比链表B长,便于后续计算
if(lenB > lenA){
int tempLen = lenA;
lenA = lenB;
lenB = tempLen;
ListNode tempNode = curA;
curA = curB;
curB = tempNode;
}
int sub = lenA - lenB;
//让链表A跑到链表B的起始位置
while(sub-- > 0){
curA = curA.next;
}
while(curA != null){
if(curA == curB){
return curA;
}
curA = curA.next;
curB = curB.next;
}
return null;
}
题目链接141环形链表1
思路:定义一个快指针和慢指针,如果有环的话,以不同速度前进的两个指针一定会相遇。当慢指针一次走一步,快指针一次走两步,当快指针能走到终点的话则不存在环,当快指针能追到慢指针的话则存在环。
代码如下:
public boolean hasCycle(ListNode head) {
ListNode fast = head, slow = head;
while(fast != null && fast.next != null){//以防fast.next为空指针
slow = slow.next;
fast = fast.next.next;
if(slow == fast){
return true;
}
}
return false;
}
题目链接142环形链表2
思路:承接上一题,从两个指针第一次相遇开始,慢指针回到起点,快指针保持原位不变,慢指针和快指针一次都走一步当再次相遇时,地点就是环的入口。
代码如下:
public ListNode detectCycle(ListNode head) {
ListNode fast = head, slow = head;
while(fast != null && fast.next != null){//以防fast.next为空指针
slow = slow.next;
fast = fast.next.next;
if(slow == fast){
slow = head;
while(true){
if(slow == fast){//以防链表是首尾相连的大回环
return fast;
}
fast = fast.next;
slow = slow.next;
}
}
}
return null;
}