怎么说,这道题看上去挺简单的,但是要搞清楚的知识点那还真不少,刷题好痛苦,但是要刷!嘿嘿~
首先,要搞懂归并排序,然后是递归。这道题我刚开始想的是递归,但是题友说时间超限,所以我就复习了一下归并,废话挺多的,嘿嘿,见谅啦~
很简单,就是遍历一下链表,然后将链表的每个结点的值都丢到set集合里面。然后再遍历set集合,将排序号的值给原本的链表即可。所以,代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
if(!head) return nullptr;
//c++中标准的容器,用以存储整数,升序排列
multiset<int> set;
ListNode* ptr=head;
//遍历加入set集合中
while(ptr){
set.insert(ptr->val);
ptr=ptr->next;
}
//改变遍历起始点
ptr=head;
//待自动排好序之后,再遍历set集合,改变原有链表中的值
for(auto it=set.begin();it!=set.end();it++){
ptr->val=*it;
ptr=ptr->next;
}
return head;
}
};
首先,什么是归并呢?就是将一条链表从中间断开,然后再对两边的进行重复操作,直到只有一个元素无法操作为止(这也是递归的终止条件)。然后再比较大小进行合并。我没搞懂的在于最后递归返回的值那,两个眼睛都变成斗鸡眼了,还是不知道为啥最后递归的值到底是怎么返回的,心真的累~但是最后想通了。
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
//思路就是将链表分成两半就行,再往下的细分工作就通过递归来完成
ListNode* sortList(ListNode* head) {
return sortList(head,nullptr);
}
ListNode* sortList(ListNode* head,ListNode* tail){
if(head==nullptr){
return head;
}
if(head->next==tail){
head->next=nullptr;
return head;
}
ListNode* slow=head,*fast=head;
while(fast!=tail){
slow=slow->next;
fast=fast->next;
if(fast!=tail){
fast=fast->next;
}
}
ListNode* mid=slow;
return merge(sortList(head,mid),sortList(mid,tail));
}
ListNode* merge(ListNode* head1,ListNode* head2){
ListNode* dumyHead=new ListNode(0);
ListNode* temp=dumyHead,*temp1=head1,*temp2=head2;
while(temp1!=nullptr&&temp2!=nullptr){
if(temp1->val<=temp2->val){
temp->next=temp1;
temp1=temp1->next;
}else{
temp->next=temp2;
temp2=temp2->next;
}
temp=temp->next;
}
//当两边有一个为空时,此时接上即可
if(temp1==nullptr) temp->next=temp2;
else temp->next=temp1;
return dumyHead->next;
}
};