文章目录
前言
温故知新
一、可出算法
二、解决
1. 从尾到头打印链表
2. 反转链表
public ListNode ReverseList(ListNode head) {
if(head == null || head.next == null) return head;
ListNode pre = null, cur = head, next = null;
while(cur != null) {
next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
3. 合并两个排序的链表
public ListNode Merge(ListNode list1,ListNode list2) {
if(list1 == null) return list2;
if(list2 == null) return list1;
ListNode preHead = new ListNode(-1);
ListNode cur1 = list1, cur2 = list2, cur = preHead;
while(cur1 != null && cur2 != null) {
if(cur1.val < cur2.val) {
cur.next = cur1;
cur1 = cur1.next;
} else {
cur.next = cur2;
cur2 = cur2.next;
}
cur = cur.next;
}
if(cur1 != null) {
cur.next = cur1;
}
if(cur2 != null) {
cur.next = cur2;
}
return preHead.next;
}
4. 两个链表的第一个公共节点
误区:计数
- 两个链表是肯定有公共节点的——null
- 如果在循环过程中,有遇到公共节点,直接返回;否则,交换链表头并遍历到链表末尾时,结束循环
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if(pHead1 == null || pHead2 == null) {
return null;
}
ListNode cur1 = pHead1, cur2 = pHead2;
while(cur1 != cur2) {
if(cur1 != null) {
cur1 = cur1.next;
} else {
cur1 = pHead2;
}
if(cur2 != null) {
cur2 = cur2.next;
} else {
cur2 = pHead1;
}
}
return cur1;
}
5. 链表中环的入口节点
public ListNode EntryNodeOfLoop(ListNode pHead) {
if(pHead == null || pHead.next == null) return null;
ListNode fast = pHead, slow = pHead;
while(true) {
if(fast == null || fast.next == null) {
return null;
}
fast = fast.next.next;
slow = slow.next;
if(fast == slow) {
break;
}
}
fast = pHead;
while(fast != slow) {
fast = fast.next;
slow = slow.next;
}
return fast;
}
6. 链表中倒数最后 K 个节点
- 快慢指针
public ListNode FindKthToTail (ListNode pHead, int k) {
if(pHead == null) return null;
ListNode fast = pHead;
while(k > 0) {
if(fast != null) {
fast = fast.next;
k--;
} else {
return null;
}
}
ListNode slow = pHead;
while(fast != null) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
7. 复杂链表的复制
public class RandomListNode {
int label;
RandomListNode next = null;
RandomListNode random = null;
RandomListNode(int label) {
this.label = label;
}
}
public RandomListNode Clone(RandomListNode pHead) {
if(pHead == null) return pHead;
RandomListNode cur = pHead;
while(cur != null) {
RandomListNode newCur = new RandomListNode(cur.label);
newCur.next = cur.next;
cur.next = newCur;
cur = cur.next.next;
}
cur = pHead;
while(cur != null) {
cur.next.random = (cur.random != null) ? cur.random.next: null;
cur = cur.next.next;
}
cur = pHead;
RandomListNode oldCur = pHead, newCur = pHead.next, newHead = newCur;
while(oldCur != null) {
oldCur.next = oldCur.next.next;
newCur.next = (newCur.next != null) ? newCur.next.next : null;
oldCur = oldCur.next;
newCur = newCur.next;
}
return newHead;
}
8. 删除链表中重复的节点
public ListNode deleteDuplication(ListNode pHead) {
if(pHead == null || pHead.next == null) return pHead;
ListNode newHead = new ListNode(-1);
newHead.next = pHead;
ListNode cur = pHead, pre = newHead;
while(cur != null) {
if(cur.next != null && cur.val == cur.next.val) {
while(cur.next != null && cur.val == cur.next.val) {
cur.next = cur.next.next;
}
cur = cur.next;
pre.next = cur;
} else {
pre = cur;
cur = cur.next;
}
}
return newHead.next;
}
9. 删除链表中的节点
public ListNode deleteNode (ListNode head, int val) {
if(head == null) return null;
if(head.val == val) {
head = head.next;
}
ListNode pre = null, cur = head;
while(cur != null) {
if(cur.val != val) {
pre = cur;
cur = cur.next;
} else {
pre.next = cur.next;
break;
}
}
return head;
}