反转链表是一道比较基础的问题,如果没有做过的话,第一次要在面试场上写出来还是有点困难的。面试官一般使用链表问题来评价面试者的编码能力。
1. 反转单链表
题意已经很明显了,就是给你一个单链表的头指针$head$,完成链表的反转,返回链表的新头部。对于这个问题,记住下面的算法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class ReverseLinkedList { public static ListNode reverse(ListNode head) { ListNode pre = null, cur = head, next; while(cur != null) { next = cur.next; cur.next = pre; pre = cur; cur = next; } return pre; } private static class ListNode { int val; Node next; } }
|
测评链接:https://leetcode.cn/problems/reverse-linked-list/
2. 反转双向链表
思路和上面的是一样的,只需要在反转的时候调整一下$pre$指针即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class ReverseDoubleLinkedList { public static ListNode reverse(DoubleListNode head) { DoubleListNode pre0 = null, cur = head, next; while(cur != null) { next = cur.next; cur.next = pre0; cur.pre = next; pre0 = cur; cur = next; } return pre; } private static class DoubleListNode { int val; Node next, pre; } }
|
3. 反转链表的一部分
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。例如:head = [1,2,3,4,5], left = 2, right = 4,返回[1,4,3,2,5]
题目链接:https://leetcode.cn/problems/reverse-linked-list-ii/
完成这个问题需要三步:
- 找到那个需要反转的那一段链表;
- 断开需要反转的那部分,把它进行反转;
- 把反转后的链表重新放回原来的链表中去。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| public class ReverseLinkedList2 { public static ListNode reverse(ListNode head, int left, int right) { if(head == null || left == right) return head; ListNode dummy = new ListNode(-1), pre, start, next, t; dummy.next = head; pre = dummy; int i = 0; for(; i != left - 1; pre = pre.next, ++i); start = pre.next; t = pre; for(; i != right; t = t.next, ++i); next = t.next; t.next = null; pre.next = reverse(start); start.next = next; return dummy.next; } public static ListNode reverse(ListNode head) { ListNode pre = null, cur = head, next; while(cur != null) { next = cur.next; cur.next = pre; pre = cur; cur = next; } return pre; } private static class ListNode { int val; Node next; ListNode(int v) { val = v; } } }
|
4. K 个一组翻转链表
题目来自于leetcode,原题。
如果会做上面那个题,那么这个题目也就不难了。只要把握住找到关键节点,断开,反转,重连这几个步骤即可。如下图所示:
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| public class ReverseLinkedListKGroup { public static ListNode reverse(ListNode head, int k) { if(head == null || k == 1) return head; ListNode dummy = new ListNode(-1), pre = dummy, start, next, t; dummy.next = head; int i; while(true) { start = pre.next; i = 1; t = start; for(; i != k && t != null; t = t.next, ++i); if(t != null) { next = t.next; t.next = null; } else break; pre.next = reverse(start); start.next = next; pre = start; } return dummy.next; } public static ListNode reverse(ListNode head) { ListNode pre = null, cur = head, next; while(cur != null) { next = cur.next; cur.next = pre; pre = cur; cur = next; } return pre; } private static class ListNode { int val; Node next; ListNode(int v) { val = v; } } }
|