与链表有关的题基本都是插入,删除,交换顺序等,解决这些问题通常将链表的指针进行修改。
问题分析:这道题本意就是对单链表进行排序,第一种方法就是新建一个结点,进行头插,遍历,比较,排序,时间复杂度为O(n^2);第二种方法是**归并排序** ,归并排序说简单些就是将一堆n个数分成n个块,然后将n个块弄成大点的n/2个块,直到合成一个块。那么如何归并呢?会合并两个有序单链表吧,也会寻找单链表的中间结点吧,在这两个算法基础上就可以对单链表进行排序,时间复杂度为O(nlogn)。
本题解析所用的编程语言:c++
归并排序法:
//快慢指针寻找中间结点 ListNode* split(ListNode* head) { ListNode* slow = head, * fast = head->next; while (fast != nullptr && fast->next != nullptr) { slow = slow->next; fast = fast->next->next; } ListNode* mid = slow->next; slow->next = nullptr; //断尾 return mid; } //合并两个有序链表 ListNode* mergeTwoLists(ListNode* head1, ListNode* head2) { ListNode head(0), * p = &head; while (head1 != nullptr && head2 != nullptr) { if (head1->val < head2->val) { p->next = head1; head1 = head1->next; } else { p->next = head2; head2 = head2->next; } p = p->next; } //至少有一个链表为空,cur->next连接不为空的链表 p->next = (head1 ? head1 : head2); return head.next; } ListNode* sortList(ListNode* head) { // write code here if (head == nullptr || head->next == nullptr) return head; ListNode* head1 = head; ListNode* head2 = split(head); head1 = sortList(head1); head2 = sortList(head2); return mergeTwoLists(head1, head2); }
头插法:
ListNode* sortList(ListNode* head) { // write code here if (head == nullptr || head->next == nullptr) return head; ListNode newhead(-1); newhead.next = head; ListNode* cur = head->next; //用来遍历head链表 ListNode* p1 = &newhead; //用来进行插入 newhead.next->next = nullptr; //末尾结点指针置空 while (cur) { while (p1->next && cur->val > p1->next->val) p1 = p1->next; ListNode* p2 = p1->next; p1->next = cur; ListNode* next = cur->next; cur->next = p2; cur = next; //插入完一个结点后,p1重新赋值 p1 = &newhead; } return newhead.next; }