148. 排序链表
1. 题目描述
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0
输出: -1->0->3->4->5
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2.代码如下(O(n^2))
typedef struct ListNode node;
struct ListNode* sortList(struct ListNode* head){
if (head == NULL || head->next == NULL)
{
return head;
}
node *tmphead = head;
node *ptail = head;
node *pCur = head->next;
while (pCur != NULL)
{
if (pCur->val <= tmphead->val)//将当前要进行排序的节点和有序序列中的头节点比较,若小于头节点,则直接头插
{
ptail->next = pCur->next;
pCur->next = tmphead;
tmphead = head = pCur;
pCur = ptail->next;
}
else
{
if (pCur->val >= ptail->val)//将当前要进行排序的节点和有序列表中的最后一个元素比较,若大于,则直接尾插
{
tmphead = head;
ptail = pCur;
pCur = pCur->next;
}
else//进入这里,可以确定当前节点在有序序列的插入范围即不在头也不在尾,只能在有序序列中间查找到它的插入位置
{
while (tmphead->next != pCur)//确保是在有序序列的范围内查找
{
if (pCur->val > tmphead->next->val)
{
tmphead = tmphead->next;
}
else //得到插入位置,插入
{
ptail->next = pCur->next;
pCur->next = tmphead->next;
tmphead->next = pCur;
pCur = ptail->next;
tmphead = head;
break;
}
}
}
}
}
return head;
}
3.nlogn的空间复杂度的做法
2中的做法时间复杂度为O(n^2),现在给一个O(nlogn)的,现在面试太难了,大家都会的题目,面试官就考要求更优的解法!
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode node;
node *cutlist(node *list,int size)
{
node *p = list;
while (p && size>1)
{
p = p->next;
--size;
}
if (!p)
{
return p;
}
node *newhead = p->next;
p->next = NULL;
return newhead;
}
node *mergelist(node *list1,node *list2)
{
node tmp;
tmp.next = NULL;
node *pnewlist = &tmp;
while (list1 && list2)
{
if (list1->val <= list2->val)
{
pnewlist->next = list1;
list1 = list1->next;
pnewlist = pnewlist->next;
}
else
{
pnewlist->next = list2;
list2 = list2->next;
pnewlist = pnewlist->next;
}
}
if (list1)
{
pnewlist->next = list1;
}
if (list2)
{
pnewlist->next = list2;
}
return tmp.next;
}
struct ListNode* sortList(struct ListNode* head){
node *cur = NULL;
node tmp;
memset(&tmp,0,sizeof(tmp));
tmp.next = head;
node *tail = NULL;
int length = 0;
node *p = head;
while (p)
{
length++;
p = p->next;
}
if (length <=1)
{
return head;
}
printf("%d\n",length);
for (int i = 1; i < length;i<<=1)
{
printf("%d\n",i);
cur = tmp.next;
tail = &tmp;
while (cur)
{
node *left = cur;
node *right = cutlist(left,i);
cur = cutlist(right,i);
tail->next = mergelist(left,right);
while (tail->next)
{
tail = tail->next;
}
}
}
return tmp.next;
}