代码随想录算法训练营第四天| 24. 两两交换链表中的节点、 19.删除链表的倒数第N个节点 、 面试题 02.07. 链表相交、 142.环形链表II
•
算法结构
24. 两两交换链表中的节点
- 刷题
https://leetcode.cn/problems/swap-nodes-in-pairs/description/ - 文章讲解
https://programmercarl.com/0024.%E4%B8%A4%E4%B8%A4%E4%BA%A4%E6%8D%A2%E9%93%BE%E8%A1%A8%E4%B8%AD%E7%9A%84%E8%8A%82%E7%82%B9.html - 视频讲解
https://www.bilibili.com/video/BV1YT411g7br/?vd_source=af4853e80f89e28094a5fe1e220d9062 -
简单图示:

-
题解:
/**
* 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 int size(ListNode head){
// 如果传入空链表,直接返回链表大小为0
if(head == null){
return 0;
}
// 链表可以保证至少头结点不为空,长度至少为1
ListNode cur = head;
int size = 1;
while(cur.next != null){
cur = cur.next;
size++;
}
return size;
}
public ListNode swapPairs(ListNode head) {
ListNode dummyhead = new ListNode();
dummyhead.next = head;
ListNode current = dummyhead;
if(size(head) % 2 == 0){
// 如果链表长度为偶数
while(current.next != null){
ListNode temp = current.next;
ListNode temp1 = current.next.next.next;
current.next = current.next.next;
current.next.next = temp;
temp.next = temp1;
current = current.next.next;
}
}else{
// 如果链表长度为奇数
while(current.next.next != null){
ListNode temp = current.next;
ListNode temp1 = current.next.next.next;
current.next = current.next.next;
current.next.next = temp;
temp.next = temp1;
current = current.next.next;
}
}
return dummyhead.next;
}
}
19.删除链表的倒数第N个节点
- 刷题
https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/ - 文章讲解
https://programmercarl.com/0019.%E5%88%A0%E9%99%A4%E9%93%BE%E8%A1%A8%E7%9A%84%E5%80%92%E6%95%B0%E7%AC%ACN%E4%B8%AA%E8%8A%82%E7%82%B9.html - 视频讲解
https://www.bilibili.com/video/BV1vW4y1U7Gf/?vd_source=af4853e80f89e28094a5fe1e220d9062 -
简单图示:

-
题解(快慢指针解法):
/**
* 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 dummyhead = new ListNode();
dummyhead.next = head;
ListNode fast = dummyhead;
ListNode low = dummyhead;
// 为了保证low移动到待删除目标结点的前驱结点
n++ ;
// 将fast移动n+1步,(从fast往回数第n个,要把low停在倒数第n个结点的前驱结点)
// 若n>链表长度,则fast停在尾结点后驱null
while(n != 0 && fast != null){
fast = fast.next;
n--;
}
// fast和low同时后移,直到fast移到最后的null
while(fast != null){
fast = fast.next;
low = low.next;
}
// 此时,low.next为倒数第n个结点
low.next = low.next.next;
return dummyhead.next;
}
}
面试题 02.07. 链表相交
- 刷题
https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/description/?envType=list&envId=t7YY2L76 - 文章讲解
https://programmercarl.com/%E9%9D%A2%E8%AF%95%E9%A2%9802.07.%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4.html -
题解1简单图示:

-
题解1(借鉴了大佬的题解,优雅,实在是优雅):
/**
* 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;
while(curA != curB){
curA = curA==null ? headB : curA.next;
curB = curB==null ? headA : curB.next;
}
return curA;
}
}
-
题解(自己写的,但是系统显示超时,Emm感觉思路没问题但是就是超时,望大佬指正) :
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
// 得到传入链表的长度
public int size(ListNode head){
// 如果传入链表为空,直接返回0
if(head == null){
return 0;
}
// 此时至少链表不为空
int size = 1;
ListNode cur = head;
while(cur.next != null){
cur = cur.next;
size++;
}
return size;
}
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode curA = headA;
ListNode curB = headB;
int result = size(headA) - size(headB);
// 当链表A长度>=链表B长度时
if(result >= 0){
// 将两个链表末端对齐
while(result != 0 && curA.next != null){
curA = curA.next;
result--;
}
while(curA != null || curB != null){
// 当A、B指针均未走到末尾向后搜索时
// 遇到两个指针相等(即两个结点相同)
if(curA == curB){
return curA;
}
}
// 若无交点,返回null
return null;
}else{
// 当B链表长度>A链表长度时
// 将两个链表末端对齐
while(result != 0 && curB.next != null){
curB = curB.next;
result++;
}
while(curA != null || curB != null){
// 当A、B指针均未走到末尾向后搜索时
// 遇到两个指针相等(即两个结点相同)
if(curA == curB){
return curB;
}
}
// 若无交点,返回null
return null;
}
}
}
142.环形链表II
- 刷题
https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/description/?envType=list&envId=t7YY2L76 - 文章讲解
https://programmercarl.com/0142.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8II.html - 视频讲解
https://www.bilibili.com/video/BV1if4y1d7ob/?vd_source=af4853e80f89e28094a5fe1e220d9062 -
数学推导:
tips:需要注意的点是:经过推导,将环拉直,不难得出low在进入环之后,走完一圈之前必然被fast追上过,所以设low为x+y。

-
题解(数学推导是重点):
/**
* 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 = head;
ListNode low = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
low = low.next;
// 遇到环,快慢指针相遇
if(fast == low){
ListNode cur1 = fast;
ListNode cur2 = head;
while(cur1 != cur2){
cur1 = cur1.next;
cur2 = cur2.next;
}
// cur1/cur2相遇点即为环入口
return cur1;
}
}
// fast走完未遇到环,说明链表无环,返回null
return null;
}
}
本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://net2asp.com/c418e36211.html
