特别说明:参考了很多前辈的文章,整理如下,我只做了重新编码的工作,不能保证代码最优,主要用作交流学习。
题目:
方法1:将链表的每个节点地址保存在指针数组中,利用数组随机访问调整链表。
1 struct ListNode 2 { 3 int val; 4 ListNode *next; 5 ListNode(int x) : val(x), next(NULL) {} 6 }; 7 8 void reorderList(ListNode *head) 9 { 10 if (head == nullptr) 11 { 12 return; 13 } 14 15 vector<ListNode *> vecNode; 16 vector<ListNode *>::size_type left, right; 17 ListNode *p = head; 18 while (p) 19 { 20 vecNode.push_back(p); 21 p = p->next; 22 } 23 24 left = 0; 25 right = vecNode.size() - 1; 26 while (left < right) 27 { 28 vecNode[left++]->next = vecNode[right]; 29 vecNode[right--]->next = vecNode[left]; 30 } 31 vecNode[left]->next = nullptr; 32 }
方法2:利用快慢两个指针将链表一分为二,针对第二个子链表求倒序,最后将两个子链表合并。
1 class Solution { 2 public: 3 ListNode *GetMid(ListNode *head) //找到链表中点 4 { 5 if (head == nullptr || head->next == nullptr) 6 { 7 return head; 8 } 9 10 ListNode *slow = head; 11 ListNode *fast = head->next; 12 13 while (fast && fast->next) 14 { 15 slow = slow->next; 16 fast = fast->next->next; 17 } 18 return slow; 19 } 20 21 ListNode *ReverseList(ListNode *head) //链表逆置 22 { 23 if (head == nullptr || head->next == nullptr) 24 { 25 return head; 26 } 27 28 ListNode *p = head; 29 ListNode *q = head->next; 30 ListNode *tmp = nullptr; 31 32 while (q) 33 { 34 tmp = q->next; 35 q->next = p; 36 p = q; 37 q = tmp; 38 } 39 head->next = nullptr; 40 41 return p; 42 } 43 44 ListNode *UnionList(ListNode *head1, ListNode *head2) //合并链表 45 { 46 if (head1 == nullptr) 47 { 48 return head2; 49 } 50 if (head2 == nullptr) 51 { 52 return head1; 53 } 54 55 ListNode *p = head1; 56 ListNode *q = head2; 57 ListNode *tmpp = nullptr; 58 ListNode *tmpq = nullptr; 59 60 while (p && q) 61 { 62 tmpp = p->next; 63 tmpq = q->next; 64 65 p->next = q; 66 q->next = tmpp; 67 68 p = tmpp; 69 q = tmpq; 70 } 71 72 return head1; 73 } 74 75 void reorderList(ListNode *head) //链表重排 76 { 77 if (head == nullptr || head->next == nullptr) 78 { 79 return; 80 } 81 82 ListNode *head1 = nullptr; 83 ListNode *head2 = nullptr; 84 ListNode *mid = nullptr; 85 86 mid = GetMid(head); 87 head2 = mid->next; 88 mid->next = nullptr; //分割成两个链表 89 90 head2 = ReverseList(head2); 91 head1 = head; 92 head = UnionList(head1, head2); 93 } 94 95 };
测试你的代码:
这里我提供一种比较好的方法,就是从文件中读入测试数据(多行),然后再分别对每行数据进行reorderList,这样可以方便同时测试多组数据。参考代码如下:
1 void CreateList(ListNode **head, ListNode **tail, ListNode *n) //创建链表 2 { 3 if (n != NULL) 4 { 5 if (*head == NULL) 6 { 7 *head = n; 8 *tail = n; 9 (*tail)->next = NULL; 10 } 11 else 12 { 13 (*tail)->next = n; 14 (*tail) = n; 15 (*tail)->next = NULL; 16 } 17 } 18 } 19 20 int main(void) 21 { 22 ifstream in("data.txt"); //打开data文件 23 string line; 24 int val; 25 ListNode *head = NULL; 26 ListNode *tail = NULL; 27 ListNode *n = NULL; 28 29 while (getline(in, line)) //每次读取一行数据至line中 30 { 31 istringstream clin(line); 32 while (clin >> val) //从每行数据中每次读取一个数据 33 { 34 n = new ListNode(val); 35 CreateList(&head, &tail, n); 36 } 37 38 Solution List; 39 List.reorderList(head); 40 41 while (head != NULL) 42 { 43 cout << head->val << ‘ ‘; 44 head = head->next; 45 } 46 cout << endl; 47 48 } 49 50 return 0; 51 }
效果如下:
说明:通过阅读很多优秀的博客,采用方法2的最多,简单清晰。
时间: 2024-10-22 12:31:23