剑指 Offer II 026. 重排链表(143. 重排链表)
题目:
思路:
【1】利用辅助空间的方式:先遍历一遍链表,将所有节点都存于数组中,然后按顺序一头一尾的配对连起来即可。
【2】不利用辅助空间的方式:先找出中位节点,拆分成两条链表(由于是链表,所以将指针指向一断就分成两条了,保留后半部分的首节点能拿到即可),将后半部分进行反转,再将两者合并。
代码展示:
利用辅助空间的方式:
//时间3 ms击败34.11% //内存43.9 MB击败79.64% //时间复杂度:O(N),其中 N 是链表中的节点数。 //空间复杂度:O(N),其中 N 是链表中的节点数。主要为线性表的开销。 /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public void reorderList(ListNode head) { if (head == null) return; List<ListNode> list = new ArrayList<ListNode>(); ListNode node = head; while (node != null) { list.add(node); node = node.next; } int i = 0, j = list.size() - 1; while (i < j) { list.get(i).next = list.get(j); i++; if (i == j) { break; } list.get(j).next = list.get(i); j--; } list.get(i).next = null; } }
不利用辅助空间的方式:
//时间1 ms击败99.93% //内存43.9 MB击败68.23% //时间复杂度:O(N),其中 N 是链表中的节点数。 //空间复杂度:O(1)。 /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public void reorderList(ListNode head) { //这三种情况分别代表[],[1],[1,2]这三种情况,都是不需要变化的 if(head == null) return; if (head.next == null) return; if (head.next.next == null) return; ListNode mid = middleNode(head); ListNode l1 = head; ListNode l2 = mid.next; mid.next = null; l2 = reverseList(l2); mergeList(l1, l2); } //利用快慢指针遍历出中位节点 public ListNode middleNode(ListNode head) { ListNode slow = head; ListNode fast = head; while (fast.next != null && fast.next.next != null) { slow = slow.next; fast = fast.next.next; } return slow; } //将中位节点的后半部分进行反转 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; } //将两部分再进行合并 public void mergeList(ListNode l1, ListNode l2) { ListNode l1_tmp; ListNode l2_tmp; while (l1 != null && l2 != null) { l1_tmp = l1.next; l2_tmp = l2.next; l1.next = l2; l1 = l1_tmp; l2.next = l1; l2 = l2_tmp; } } }