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}
.
题目的意思就是,给定一个链表,从两头开始链接,
比如1-2-3-4-5-6,最开始取两头,组成1-6,剩下2-3-4-5;
接着取两头,2-5,和上面的1-6连接起来,组成1-6-2-5,剩下3-4;
接着取两头, 3-4,同理和上面的结果连接起来,组成 1-6-2-5-3-4;
我一共做了3种解法:第一种解法,使用递归的解法,每次都取两头,然后递归的去解;一共递归n/2次,每次需要从头开始遍历到最后一个元素,需要n步,所以时间复杂度是O(N*N),, 空间复杂度O(1). 但是结果是超时了。。。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *recurse(ListNode *head) { if(head == NULL || head->next == NULL) { return head; } ListNode *cur = head, *pre = head; while(cur->next != NULL) { pre = cur; cur = cur->next; } pre->next = NULL; ListNode *next = head->next; head->next = cur; cur->next = recurse(next); return head; } void reorderList(ListNode *head) { if(head == NULL || head->next == NULL) return; head =recurse(head); } };
第二种解法,比较有效率,O(N)的时间复杂度,O(1)空间复杂度。思路是:将链表平均分为前后2段(l和r),将r倒转,然后按照顺序将l和r拼接起来。AC了
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *split(ListNode *head) { ListNode *p = head; ListNode *q = head->next; while(q != NULL && q->next != NULL) { q = q->next->next; p = p->next; } q = p->next; p->next = NULL; return q; } ListNode *reverse(ListNode *head) { if(head == NULL || head->next == NULL) return head; ListNode *pre = head, *cur = head->next, *next; head->next = NULL; while(cur != NULL) { next = cur->next; cur->next = pre; pre = cur; cur = next; } return pre; } void reorderList(ListNode *head) { if(head == NULL || head->next == NULL) return; ListNode *r = reverse(split(head)); ListNode *l = head->next; ListNode *traverse = head; while(r != NULL && l != NULL) { ListNode *tmp_r = r->next; ListNode *tmp_l = l->next; traverse->next = r; traverse = traverse->next; traverse->next = l; traverse = traverse->next; l = tmp_l; r = tmp_r; } if(r != NULL) traverse->next = r; else traverse->next = l; } };
最后一种解法是最直接的,借助了一个O(N)的空间,写起来比较简单,而且代码很容易懂,依然O(N)的时间复杂度,比第二种解法快了3ms。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: void reorderList(ListNode *head) { if(head == NULL || head->next == NULL) return; vector<ListNode *> vec; ListNode *p = head->next; while(p != NULL) { vec.push_back(p); p = p->next; } p = head; vector<ListNode *>::size_type i, j; for(i = 0, j = vec.size() - 1; i < j; i++, j--) { p->next = vec[j]; p = p->next; p->next = vec[i]; p = p->next; } if(i == j) { p->next = vec[i]; p = p->next; } p->next = NULL; } };
时间: 2024-11-04 12:41:18