知识点1:分治
分治即“分而治之”,“分“指的是将一大而复杂的问题划分成多人性质相同但是规模更小的子问题,子问题继续技照这样划分,直到问题可以被轻易解决,"治”指的是将子问题单独进行处理,经过分治后的子问题,需要将解进行合并才能得到原问题的解,因此整个分治过程经常用说归来实现。
知识点2: 双指针
双指针指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个指计(特殊情况甚至可以多个)》,两个指计或是同方向访问两个链表、或是同方向访问一个链表(快慢指针)、或是相反方向扫描(对撞指针),从而达到我们需要的目的。
具体做法:
1、首先判断链表为空或者只有一个元素,直接就是有序的
2、准备三个指针,快指right每次走两步,便指针mid每次走一步,前序指针ef每次跟在mid前一个位置。三个指针遍历链表,当快指针到达链表尾部的时候,慢指针mid刚好走了链表的一半,正好是中间位置
3、从left位置将链表断开,刚好分成两个子问题开始递归
4、将子问题得到的链表合并,参考合并两个有序链表
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *merge(struct ListNode *head1, struct ListNode *head2)
{
if(head1 == NULL){
return head2;
}
if(head2 == NULL){
return head1;
}
//add list head
struct ListNode head;
struct ListNode *cur = &head;
while (head1 && head2) {
if(head1->val <= head2->val){
cur->next = head1;
head1 = head1->next;
}
else{
cur->next = head2;
head2 = head2->next;
}
cur = cur->next;
}
if(head1){
cur->next = head1;
}
else{
cur->next = head2;
}
return head.next;
}
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类 the head node
* @return ListNode类
*/
struct ListNode* sortInList(struct ListNode* head ) {
// write code here
//链表为空、只有一个元素,直接就是有序
if(head == NULL || head->next == NULL){
return head;
}
struct ListNode *left = head;
struct ListNode *mid = head->next;
struct ListNode *right = head->next->next;
//右边指针到达末尾时,中间指针指向该段链表的中间
while (right != NULL && right->next != NULL) {
left = left->next;
mid = mid->next;
right = right->next->next;
}
//左边指针指向左端的左右一个节点,从这里断开
left->next = NULL;
//分成两段排序,合并有序的两端
return merge(sortInList(head), sortInList(mid));
}