网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
//update pCur
pCur = pNext;
}
return dummy.next;
}
##### 二、单向链表的归并排序
###### 题目:
Sort a linked list in O(n log n) time using constant space complexity.
###### 分析:
因为题目要求复杂度为O(nlogn),故可以考虑归并排序的思想。
归并排序的一般步骤为:
1)将待排序数组(链表)取中点并一分为二;
2)递归地对左半部分进行归并排序;
3)递归地对右半部分进行归并排序;
4)将两个半部分进行合并(merge),得到结果。
所以对应此题目,可以划分为三个小问题:
1)找到链表中点 (快慢指针思路,快指针一次走两步,慢指针一次走一步,快指针在链表末尾时,慢指针恰好在链表中点);
2)写出merge函数,即如何合并链表。
3)写出mergesort函数,实现上述步骤。
不过这里需要**注意**的是:寻找链表的中点,当链表节点个数为偶数时,需要返回中值靠左的节点,比如当只有两个数时,返回第一个数位置的索引。目的是使分治结束。
###### 代码:
1. 快慢指针;2. 归并排序。
链表的归并排序空间复杂度是O(1)。
//找到链表中间位置(奇数中间那个,偶数偏左那个)
ListNode *Find_middle(ListNode *head)
{
if (!head || !head->next) return head;
//使用快,慢指针的方法:慢指针走一步,快指针走两步
ListNode \*slow = head, \*fast = head->next;
while (fast !=NULL && fast->next != NULL)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if (pHead1 == NULL) return pHead2;
if (pHead2 == NULL) return pHead1;
ListNode mergeNode(0);
ListNode \*pNew = &mergeNode; //合并指针
while (pHead1 && pHead2)
{
if (pHead1->val <= pHead2->val)
{
pNew->next = pHead1;
pHead1 = pHead1->next;
}
else
{
pNew->next = pHead2;
pHead2 = pHead2->next;
}
pNew = pNew->next;
}
if (pHead1)
pNew->next = pHead1;
if (pHead2)
pNew->next = pHead2;
return mergeNode.next;
}
ListNode *sortList(ListNode *head) {
if (head == NULL || head->next == NULL) return head;
ListNode \*pMid = Find_middle(head);
ListNode \*pRightHead = pMid->next;
pMid->next = NULL;
ListNode \*left = sortList(head);
ListNode \*right = sortList(pRightHead);
return Merge(left, right);
}
##### 三、单向链表的快速排序
###### 题目:
Sort a linked list in O(nlogn) time using constant space complexity.
###### 分析:
单链表的快速排序 时间复杂度O(nlogn),空间复杂度O(n)
快速排序的主要操作是用选取的枢轴作为切割的基准,左侧所有元素均小于枢轴,右侧均不小于枢轴。经典实现是从头和尾两个方向进行处理,由于单链表的移动方向是**单向**的,所以必须寻求其他方式。
用一个指针遍历链表,遇到小于枢轴的元素,就将其移到链表的开始处,剩下的就是不小于枢轴的元素;为了实现上述目标,建立两个指针,一个指针指向所有元素都小于枢轴的子链表,一个指针用于遍历。
###### 代码:
//返回基准位置
ListNode *partitionList(ListNode* low, ListNode* high)
{
int pivot = low->val;
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!