1、单链表翻转
1)递归实现
递归短小精悍,但是理解上不是很直接,需要多练。
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) return head;
ListNode next = reverseList(head.next);
head.next.next = head;
head.next = null;
return next;
}
2)迭代实现
比较优雅的实现,最后返回的是pre节点。
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
2、两两一组翻转链表
1)迭代1
先分成两个链表然后再串起来。写的有点丑
public ListNode swapPairs(ListNode head) {
ListNode slow = head;
if (slow == null) return head;
ListNode fast = head.next;
if (fast == null) return head;
ListNode root = fast, p2 = fast;
ListNode p1 = slow;
while (fast != null){
slow.next = fast.next;
slow = slow.next;
if (slow == null) break;
fast.next = slow.next;
fast = fast.next;
}
ListNode cur = p2;
while (p2 != null){
p2 = p2.next;
cur.next = p1;
p1 = p1.next;
cur = cur.next;
if (p2 == null) break;
cur.next = p2;
cur = cur.next;
}
return root;
}
2)迭代2
有个pre辅助节点,可以串起来后续节点。
public ListNode swapPairs(ListNode head) {
ListNode dummy = new ListNode(1);
dummy.next = head;
ListNode pre = dummy;
while (pre.next != null && pre.next.next != null){
ListNode a = pre.next;
ListNode b = a.next;
a.next = b.next;
b.next = a;
pre.next = b;
pre = a;
}
return dummy.next;
}
3)递归
还是看代码比较直接。
public ListNode swapPairs(ListNode head) {
if (head == null || head.next == null) return head;
ListNode p = head;
ListNode q = p.next;
ListNode next = q.next;
q.next = p;
p.next = swapPairs(next);
return q;
}
3、k个一组翻转
有了上面的两个一组翻转的递归实现,k个一组的递归实现就水到渠成了
1)递归
public ListNode reverseKGroup(ListNode head, int k) {
if (head == null) return head;
int temp = k;
ListNode cur = head;
ListNode a = head;
while (temp-- > 0 && cur != null){
cur = cur.next;
}
if (temp >= 0) return head;
ListNode newNode = reverse(a, cur);
a.next = reverseKGroup(cur, k);
return newNode;
}
//翻转a到b直接的链表(不包含b点之前的指针)
private ListNode reverse (ListNode a, ListNode b){
ListNode cur = a;
ListNode pre = null;
while (cur != b){
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
2)迭代
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
for (ListNode pre = dummy;;){
ListNode q = pre;
for (int i = 0; i < k && q != null; i++) q = q.next;
if (q == null) break;
ListNode a = pre.next, b = a.next;
//翻转内部的k-1个节点
for (int i = 0; i < k - 1; i++){
ListNode next = b.next;
b.next = a;
a = b;
b = next;
}
ListNode c = pre.next;
pre.next = a;
c.next = b;
pre = c;
}
return dummy.next;
}
迭代看起来有点费劲,记住递归一种实现就行了。
翻转链表有很多种形式,比如还有某个区间的节点翻转等。不要着急写,画图很重要,先画图弄清思路再写代码。