143. 重排链表
题目描述
给定一个单链表 L 的头节点 head ,单链表 L 表示为:
1
   | L0 → L1 → … → Ln - 1 → Ln
   | 
 
请将其重新排列后变为:
1
   | L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
   | 
 
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
输入输出
1 2 3 4 5
   | 输入:head = [1,2,3,4] 输出:[1,4,2,3]
  输入:head = [1,2,3,4,5] 输出:[1,5,2,4,3]
   | 
 
基本思路
方法一:
- 链表不支持下标访问,所以无法随机访问链表中任意位置的元素。因此比较容易想到的一个方法是,利用线性表存储该链表,然后利用线性表可以下标访问的特点,直接按顺序访问指定元素,重建该链表即可。
 
- 性能:
- 时间复杂度:$O(N)$,其中 N 是链表中的节点数。
 
- 空间复杂度:$O(N)$,其中 N 是链表中的节点数。主要为线性表的开销。
 
 
方法二:目标链表即为将原链表的左半端和反转后的右半端合并后的结果
- 找到原链表的中点(参考「876. 链表的中间结点」)
 
- 将原链表的右半端反转(参考「剑指 Offer 24. 反转链表」)
 
- 将原链表的两端合并
 
- 性能:
- 时间复杂度:$O(N)$,其中 N 是链表中的节点数。
 
- 空间复杂度:$O(1)$
 
 
java实现
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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
   |  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;     } }
 
  class Solution {     public void reorderList(ListNode head) {         if(head == null) return;         ListNode midnode = middleNode(head);                  ListNode p1 = head;         ListNode reverse_node = midnode.next;
          midnode.next = null;                  ListNode p2 = reverse(reverse_node);         mergeTwoLists(p1, p2);     }
      public ListNode reverse(ListNode head){         ListNode cur = head, pre = null;         while(cur != null){             ListNode tmp = cur.next;             cur.next = pre;             pre = cur;             cur = tmp;         }         return pre;     }
      public ListNode middleNode(ListNode head){                  int cnt = 0;         ListNode node = head;         while(node != null){             cnt++;             node = node.next;         }         int findnode = cnt / 2;         node = head;         for(int i = 0; i < findnode; i++){             node = node.next;         }         return node;     }
      public void mergeTwoLists(ListNode p1, ListNode p2){         ListNode p1_tmp, p2_tmp;         while(p1 != null && p2 != null){             p1_tmp = p1.next;             p2_tmp = p2.next;             p1.next = p2;             p1 = p1_tmp;             p2.next = p1;             p2 = p2_tmp;         }     } }
 
  |