mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6
956 字
5 分钟
【算法笔记】(十五)链表高频题目和必备技巧
2026-04-13
统计加载中...

每K个节点一组翻转链表#

测试链接:https://leetcode.cn/problems/reverse-nodes-in-k-group/#

public ListNode reverseKGroup(ListNode head, int k) {
ListNode start = head;
ListNode end = endNode(start, k);
if (end == null) {
return head;
}
// 第一组很特殊因为牵扯到换头的问题
head = end;
reverse(start, end);
// 翻转之后start变成了上一组的结尾节点
ListNode lastTeamEnd = start;
while (lastTeamEnd.next != null) {
start = lastTeamEnd.next;
end = endNode(start, k);
if (end == null) {
return head;
}
reverse(start, end);
lastTeamEnd.next = end;
lastTeamEnd = start;
}
return head;
}
public static void reverse(ListNode s, ListNode e) {
e = e.next;
ListNode pre = null, cur = s, next = null;
while (cur != e) {
next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
s.next = e;
}
private ListNode endNode(ListNode head, int k) {
ListNode end = head;
while (-- k != 0 && end != null) {
end = end.next;
}
return end;
}

随机链表的复试#

测试链接:https://leetcode.cn/problems/copy-list-with-random-pointer/#

public Node copyRandomList(Node head) {
if (head == null) return null;
Node node = head;
while (node != null) {
Node node1 = new Node(node.val);
node1.next = node.next;
node.next = node1;
node = node1.next;
}
node = head;
while (node != null) {
if (node.random != null ) node.next.random = node.random.next;
node = node.next.next;
}
Node result = head.next;
node = head;
while (node != null) {
Node node1 = node.next;
node.next = node1.next;
if (node1.next != null) node1.next = node1.next.next;
node = node.next;
}
return result;
}

判断链表是否是回文结构#

测试链接:https://leetcode.cn/problems/palindrome-linked-list/#

public static boolean isPalindrome(ListNode head) {
if (head == null || head.next == null) {
return true;
}
ListNode slow = head, fast = head;
// 找中点
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// 现在中点就是slow,从中点开始往后的节点逆序
ListNode pre = slow;
ListNode cur = pre.next;
ListNode next = null;
pre.next = null;
while (cur != null) {
next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
// 上面的过程已经把链表调整成从左右两侧往中间指
// head -> ... -> slow <- ... <- pre
boolean ans = true;
ListNode left = head;
ListNode right = pre;
// left往右、right往左,每一步比对值是否一样,如果某一步不一样答案就是false
while (left != null && right != null) {
if (left.val != right.val) {
ans = false;
break;
}
left = left.next;
right = right.next;
}
// 本着不坑的原则,把链表调整回原来的样子再返回判断结果
cur = pre.next;
pre.next = null;
next = null;
while (cur != null) {
next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return ans;
}

返回链表的第一个入环节点#

测试链接:https://leetcode.cn/problems/linked-list-cycle-ii/#

public static ListNode detectCycle(ListNode head) {
if (head == null || head.next == null || head.next.next == null) {
return null;
}
ListNode slow = head.next;
ListNode fast = head.next.next;
while (slow != fast) {
if (fast.next == null || fast.next.next == null) {
return null;
}
slow = slow.next;
fast = fast.next.next;
}
fast = head;
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
return slow;
}

排序链表,要求时间复杂度O(n*logn),额外空间复杂度O(1),还要求稳定性#

测试链接:https://leetcode.cn/problems/sort-list/#

public static ListNode sortList(ListNode head) {
if (head == null || head.next == null) return head;
int listLen = 0;
ListNode node = head;
while (node != null) {
listLen ++;
node = node.next;
}
ListNode l1 ,r1 ,l2 ,r2 ,next ,lastEndNode = null;
for (int step = 1 ; step < listLen ;step <<= 1) {
l1 = head;
r1 = endNode(l1 ,step);
if (r1.next == null){
break;
}
l2 = r1.next;
r2 = endNode(l2 ,step);
next = r2.next;
r1.next = null;
r2.next = null;
merge (l1 ,r1 ,l2 ,r2);
lastEndNode = end;
head = start;
while (next != null) {
l1 = next;
r1 = endNode(l1 ,step);
if (r1.next == null) {
lastEndNode.next = l1;
break;
}
l2 = r1.next;
r2 = endNode(l2 ,step);
next = r2.next;
r1.next = null;
r2.next = null;
merge(l1 ,r1 ,l2 ,r2);
lastEndNode.next = start;
lastEndNode = end;
}
}
return head;
}
public static ListNode start = null ,end = null;
private static void merge(ListNode l1, ListNode r1, ListNode l2, ListNode r2) {
if (l1.val <= l2.val) {
end = l1;
start = l1;
l1 = l1.next;
} else {
end = l2;
start = l2;
l2 = l2.next;
}
while (l1 != null && l2 != null) {
if (l1.val <= l2.val) {
end.next = l1;
end = l1;
l1 = l1.next;
} else {
end.next = l2;
end = l2;
l2 = l2.next;
}
}
if (l1 != null) {
end.next = l1;
}
if (l2 != null) {
end.next = l2;
}
while (end.next != null) end = end.next;
}
private static ListNode endNode(ListNode l1, int step) {
while (l1.next != null && --step != 0) {
l1 = l1.next;
}
return l1;
}
【算法笔记】(十五)链表高频题目和必备技巧
http://hgqwd.icu/posts/suanfa15/
作者
天线宝宝死于谋杀
发布于
2026-04-13
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

封面
Sample Song
Sample Artist
封面
Sample Song
Sample Artist
0:00 / 0:00