leetcode链表相关题目
目录
1. 链表反转系列
1.1 反转链表
1.1.1 迭代版
public ListNode reverseList(ListNode head) {
ListNode newHead = null; // 指向新链表头节点的指针
while (head != null) {
ListNode next = head.next; // 备份head.next
head.next = newHead; // 更新head.next
newHead = head; // 移动newHead
head = next; // 遍历链表
}
return newHead; // 返回新链表头节点
}
1.1.2 递归版
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode cur = reverseList(head.next); // cur尾节点
// 1->2->3->4->5 head为4 cur为5
head.next.next = head; // 5->4
head.next = null; // 删除4->5
return cur;
}
1.2 反转链表II
1.2.1 迭代版
public ListNode reverseBetween(ListNode head, int m, int n) {
ListNode dummy = new ListNode(-1);
ListNode pre = dummy;
dummy.next = head;
for (int i = 0; i < m - 1; i++) pre = pre.next;
ListNode cur = pre.next;
for (int i = m; i < n; i++) {
ListNode t = cur.next;
cur.next = t.next;
t.next = pre.next;
pre.next = t;
}
return dummy.next;
}
1.2.2 递归版
public ListNode reverseBetween(ListNode head, int m, int n) {
if (m == 1) {
return reverseN(head, n);
}
head.next = reverseBetween(head.next, m - 1, n - 1);
return head;
}
private ListNode next = null;
private ListNode reverseN(ListNode head, int n) {
if (n == 1) {
next = head.next;
return head;
}
ListNode last = reverseN(head.next, n - 1);
head.next.next = head;
head.next = next;
return last;
}
1.3 两两交换链表中的节点
1.3.1 迭代版
public ListNode swapPairs(ListNode head) {
// 按原始链表顺序调整指针
if (head == null || head.next == null) return head;
ListNode node = new ListNode(-1);
ListNode res = node;
while (head != null && head.next != null) {
node.next = head.next;
head.next = head.next.next;
node.next.next = head;
node = head;
head = head.next;
}
return res.next;
}
1.3.2 递归版
public ListNode swapPairs(ListNode head) {
if (head == null || head.next == null) return head;
ListNode node = head.next;
head.next = swapPairs(node.next);
node.next = head;
return node;
}
1.4 K个一组翻转链表
public ListNode reverseKGroup(ListNode head, int k) {
if (head == null || head.next == null) return head;
ListNode tail = head;
for (int i = 0; i < k; i++) {
if (tail == null) return head;
tail = tail.next;
}
ListNode newHead = reverse(head, tail);
head.next = reverseKGroup(tail, k);
return newHead;
}
private ListNode reverse(ListNode head, ListNode tail) {
ListNode pre = null;
ListNode next = null;
while (head != tail) {
next = head.next;
head.next = pre;
pre = head;
head = next;
}
return pre;
}
1.5 回文链表
public boolean isPalindrome(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
slow = reverseList(fast == null ? slow : slow.next);
while (slow != null) {
if (slow.val != head.val) return false;
slow = slow.next;
head = head.next;
}
return true;
}
private ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode cur = reverseList(head.next); // cur尾节点
// 1->2->3->4->5 head为4 cur为5
head.next.next = head; // 5->4
head.next = null; // 删除4->5
return cur;
}
2. 链表排序系列
2.1 合并有序链表
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) return l2;
if (l2 == null) return l1;
if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
} else {
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
}
2.2 合并K个有序链表
public ListNode mergeKLists(ListNode[] lists) {
if (lists.length == 0) return null;
return solve(lists, 0, lists.length - 1);
}
private ListNode solve(ListNode[] arr, int left, int right) {
if (left == right) return arr[left];
int mid = (left + right) >> 1;
ListNode lNode = solve(arr, left, mid);
ListNode rNode = solve(arr, mid + 1, right);
return mergeTwoLists(lNode, rNode);
}
private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) return l2;
if (l2 == null) return l1;
if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
} else {
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
}
2.3 排序链表
public ListNode sortList(ListNode head) {
if (head == null || head.next == null) return head;
ListNode mid = findMiddle(head);
ListNode right = sortList(mid.next);
mid.next = null;
ListNode left = sortList(head);
return merge(left, right);
}
private ListNode findMiddle(ListNode head) {
ListNode slow = head, fast = head;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
private ListNode merge(ListNode l1, ListNode l2) {
if (l1 == null) return l2;
if (l2 == null) return l1;
if (l1.val < l2.val) {
l1.next = merge(l1.next, l2);
return l1;
} else {
l2.next = merge(l1, l2.next);
return l2;
}
}
2.4 重排链表
public void reorderList(ListNode head) {
if (head == null || head.next == null) return;
ListNode slow = head, fast = head;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
slow.next = reverseList(slow.next);
while (slow.next != null && head != null) {
ListNode cur = slow.next;
slow.next = cur.next;
ListNode t = head.next;
head.next = cur;
cur.next = t;
head = head.next.next;
}
}
private ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode cur = reverseList(head.next); // cur尾节点
// 1->2->3->4->5 head为4 cur为5
head.next.next = head; // 5->4
head.next = null; // 删除4->5
return cur;
}
2.5 删除排序链表中的重复元素
public ListNode deleteDuplicates(ListNode head) {
if (head == null || head.next == null) return head;
ListNode dummy = new ListNode(-1024);
dummy.next = head;
ListNode pre = dummy;
while (head != null) {
if (head.val == pre.val) {
pre.next = head.next;
head.next = null;
head = pre.next;
} else {
pre = head;
head = head.next;
}
}
return dummy.next;
}
2.6 删除排序链表中的重复元素II
public ListNode deleteDuplicates(ListNode head) {
if (head == null || head.next == null) return head;
if (head.val == head.next.val) {
ListNode pNode = head.next;
while (pNode != null && pNode.val == head.val) pNode = pNode.next;
return deleteDuplicates(pNode);
} else {
head.next = deleteDuplicates(head.next);
return head;
}
}
3. 链表删除系列
3.1 删除链表中的节点
public void deleteNode(ListNode node) {
node.val = node.next.val;
node.next = node.next.next;
}
3.2 删除链表倒数第N个节点
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode slow = dummy, fast = dummy;
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 dummy.next;
}
3.3 查找倒数第K个节点
public ListNode FindKthToTail(ListNode head, int k) {
ListNode fast, slow;
fast = slow = head;
int i = 0;
for (; fast != null; i++) {
if (i >= k) slow = slow.next;
fast = fast.next;
}
return i < k ? null : slow;
}
3.4 移除链表元素
public ListNode removeElements(ListNode head, int val) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode pre = dummy;
while (head != null) {
if (head.val == val) {
pre.next = head.next;
head.next = null;
head = pre.next;
} else {
pre = head;
head = head.next;
}
}
return dummy.next;
}
4. 查找中间节点
public static int findMidNode(Node head) {
if (head == null)
return -1;
Node fast = head, slow = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow.val;
}
5. 从尾到头打印链表
private ArrayList<Integer> res = new ArrayList<>();
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
if (listNode == null) return res;
printListFromTailToHead(listNode.next);
res.add(listNode.val);
return res;
}
6. 相交链表
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) return null;
ListNode ptrA = headA;
ListNode ptrB = headB;
while (ptrA != ptrB) {
ptrA = ptrA != null ? ptrA.next : headB;
ptrB = ptrB != null ? ptrB.next : headA;
}
return ptrA;
}
7. 分割链表
public ListNode partition(ListNode head, int x) {
ListNode before_head = new ListNode(0);
ListNode before = before_head;
ListNode after_head = new ListNode(0);
ListNode after = after_head;
while (head != null) {
if (head.val < x) {
before.next = head;
before = before.next;
} else {
after.next = head;
after = after.next;
}
head = head.next;
}
after.next = null;
before.next = after_head.next;
return before_head.next;
}
8. 复杂链表的复制
public Node copyRandomList(Node head) {
if (head == null) return null;
Node dummy = head;
while (dummy != null) {
Node t = new Node(dummy.val);
t.next = dummy.next;
dummy.next = t;
dummy = t.next;
}
dummy = head;
while (dummy != null) {
if (dummy.random != null) {
dummy.next.random = dummy.random.next;
}
dummy = dummy.next.next;
}
dummy = head;
Node res = head.next;
while (dummy.next != null) {
Node t = dummy.next;
dummy.next = dummy.next.next;
dummy = t;
}
return res;
}
9. 两数相加
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int k1 = getLength(l1);
int k2 = getLength(l2);
if (k1 < k2) { // 保证l1指向长链表
ListNode t = l1;
l1 = l2;
l2 = t;
}
boolean flag = false;
ListNode res = l1;
ListNode pre = null;
while (l1 != null) {
if (l1.next == null) pre = l1;
int k = l1.val + (l2 == null ? 0 : l2.val) + (flag ? 1 : 0);
flag = k >= 10;
l1.val = k % 10;
l1 = l1.next;
if (l2 != null) l2 = l2.next;
}
if (flag) pre.next = new ListNode(1);
return res;
}
private int getLength(ListNode head) {
int count = 0;
while (head != null) {
count++;
head = head.next;
}
return count;
}
10. 两数相加II
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
Stack<Integer> s1 = pushStack(l1);
Stack<Integer> s2 = pushStack(l2);
boolean flag = false;
ListNode pre = null;
while (!s1.isEmpty() || !s2.isEmpty()) {
int sum = (s1.isEmpty() ? 0 : s1.pop()) + (s2.isEmpty() ? 0 : s2.pop()) + (flag ? 1 : 0);
flag = (sum >= 10);
ListNode node = new ListNode(sum % 10);
node.next = pre;
pre = node;
}
if (flag) {
ListNode newHead = new ListNode(1);
newHead.next = pre;
pre = newHead;
}
return pre;
}
private Stack<Integer> pushStack(ListNode head) {
Stack<Integer> stack = new Stack<>();
while (head != null) {
stack.push(head.val);
head = head.next;
}
return stack;
}
11. 奇偶链表
public ListNode oddEvenList(ListNode head) {
if (head == null || head.next == null) return head;
ListNode m = head;
ListNode n = head.next;
ListNode t = head.next;
while (m.next != null) {
m.next = n.next;
if (n.next != null) {
n.next = m.next.next;
}
if (m.next != null) {
m = m.next;
}
n = n.next;
}
m.next = t;
return head;
}
12. 有序链表转二叉搜索树