题目描述
Given a singly linked list L: L0→L1→…→Ln-1→Ln,reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
You must do this in-place without altering the nodes' values.
For example,Given{1,2,3,4}, reorder it to{1,4,2,3}.
解题思路:本题的意思是要讲链表重新排序
(比较取巧的方法)
解法一:先将链表放入vector中,然后通过两个指针,一个指向第一个结点,一个指向最后结点,然后将第一个结点指向最后一个结点,然后最后一个结点指向第二个结点,然后进行下一次操作
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 void reorderList(ListNode *head) { 12 // write your code here 13 if (head == NULL) 14 return; 15 16 vector<ListNode*> nodes; 17 ListNode* iter = head; 18 while(iter != NULL) 19 { 20 nodes.push_back(iter); 21 iter = iter->next; 22 } 23 24 int LEN = nodes.size(); 25 int left = 0; 26 int right = LEN -1; 27 while(left < right) 28 { 29 nodes[left]->next = nodes[right]; 30 nodes[right--]->next = nodes[++left]; 31 } 32 nodes[left]->next = NULL; 33 } 34 };
解法二:理想情况下,如果能一个指针从后往前走,一个指针从前往后走,然后一个一个合并就行了。但是单链表并没有从后往前走的能力,难道要改造成双链表吗?其实不用,我们只要把后半部分反转一下,变成两个链表就行了。要找到后半部分的起点,就是用快慢指针。从头开始,快指针走两步,慢指针走一步,这样快指针到头的时候慢指针就是中间了。不过该题我们不能直接拿到中间,而是要拿到中间的前一个节点,这样才能把第一个子链表的末尾置为空,这里的技巧就是快慢指针循环的条件是fast.next != null && fast.next.next != null。
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 void reorderList(ListNode *head) 12 { 13 if(head == NULL) 14 return; 15 ListNode *slow = head; 16 ListNode *fast = head; 17 // 找到中点的前一个节点 18 while(fast->next != NULL && fast->next->next != NULL) 19 { 20 fast = fast->next->next; 21 slow = slow->next; 22 } 23 // 反转中点及之后的链表 24 ListNode *head2 = reverseList(slow->next); 25 // 将前半部分链表的末尾置空 26 slow->next = NULL; 27 // 找到两个子链表的头,准备开始合并 28 ListNode *head1 = head; 29 ListNode dummy(0); //创建结构体dummy(0)为l的辅助空间,因为可能在最开始插入 30 ListNode *curr = &dummy; 31 // 当子链表都不为空的时候依次合并 32 while(head2 != NULL && head1 != NULL) 33 { 34 curr->next = head1; 35 head1 = head1->next; 36 curr = curr->next; 37 curr->next = head2; 38 head2 = head2->next; 39 curr = curr->next; 40 } 41 // 当其中一个子链表为空时,把另一个链表剩下的那个节点加上,因为可能一共有奇数个节点 42 curr->next = head2 != NULL ? head2 : NULL; 43 curr->next = head1 != NULL ? head1 : NULL; 44 head = dummy.next; 45 } 46 //迭代反转链表 47 ListNode *reverseList(ListNode *head){ 48 if(head == NULL || head->next == NULL) 49 { 50 return head; 51 } 52 ListNode *p1 = head; 53 ListNode *p2 = head->next; 54 while(p2 != NULL) 55 { 56 ListNode *tmp = p2->next; 57 p2->next = p1; 58 p1 = p2; 59 p2 = tmp; 60 } 61 head->next = NULL; 62 return p1; 63 } 64 };