• leetcode148. Sort List


    题目:

    Sort a linked list in O(n log n) time using constant space complexity.

    题目解析:要求用链表作为排序的数据结构,时间复杂度为O(nlogn),空间复杂度为O(1)。

    分析:首先想到复杂度为O(nlogn)的排序算法有:快排,堆排和归并排序,三者的空间复杂度都为O(n)。本例使用归并排序,归并排序如果用数组结构存储归并排序后的数据,则需要开辟出O(n)的空间来容纳数组,空间复杂度为O(n),但是若用链表作为数据结构,只需要改变next指针指向下一个归并后的顺序就行,空间复杂度降为O(1)。

    要用归并排序,难点是:怎么样找到分治时的middle指针,采用快慢指针的思想。快指针一次走两步,慢指针一次走一步,当快指针走到头时,慢指针刚好走到中间位置,此位置即为middle的位置。

    两个有序序列的合并

     1 LinkList* mergelist(LinkList *head1,LinkList *head2)
     2 {
     3     LinkList *newhead = new LinkList(-1);
     4     LinkList *newtail;
     5     newtail = newhead;
     6     while (head1 != NULL &head2 != NULL)
     7     {
     8         if (head1->data < head2->data)
     9         {
    10             newtail->next = head1;
    11             head1 = head1->next;
    12         }else
    13         {
    14             newtail->next = head2;
    15             head2 = head2->next;
    16         }
    17         newtail = newtail->next;
    18     }
    19     if (head1 != NULL)
    20     {
    21         newtail->next= head1;
    22     }
    23     if (head2 != NULL)
    24     {
    25         newtail->next = head2;
    26     }
    27     return newhead->next;
    28 }

    得到middle指针

     1 LinkList* getmid(LinkList *head)
     2 {
     3     LinkList *fast,*slow;
     4     fast = head;
     5     slow = head;
     6     while (fast->next != NULL && fast->next->next != NULL)
     7     {
     8         fast = fast->next->next;
     9         slow = slow->next;
    10     }
    11     fast = slow->next;
    12     //从中间节点断开
    13     slow->next = NULL;
    14     return fast;
    15 }

    归并函数

     1 LinkList* sortlist(LinkList *head)
     2 {
     3     if (head == NULL || head->next == NULL)
     4     {
     5         return head;
     6     }    
     7     LinkList *mid;
     8     mid = getmid(head);
     9     head = sortlist(head);
    10     mid = sortlist(mid);
    11     head = mergelist(head,mid);
    12     return head;
    13 }

    测试例子补全:

    创建单链表:(返回是是没有头结点的链表)

     1 LinkList* createlinklist(LinkList *l,int n)
     2 {
     3     LinkList *p,*s;
     4     l = (LinkList *)malloc(sizeof(LinkList));
     5     s = l;
     6     int m;
     7     for (int i = 0; i < n;i++)
     8     {
     9         p = (LinkList *)malloc(sizeof(LinkList));
    10         cin >> m;
    11         p->data = m;
    12         s->next = p;
    13         s = p;
    14     }
    15     s->next = NULL;
    16     return l->next;
    17 }

    主函数:

     1 void main()
     2 {
     3     LinkList *l = new LinkList(-1);
     4     l = createlinklist(l,6);
     5     l = sortlist(l);
     6     for (int i = 0;i<6;i++)
     7     {
     8         cout << l->data << " ";
     9         l = l->next;
    10     }
    11     system("pause");
    12 }

    运行结果:

    在本题中用到了快慢指针,下面顺便详述一下快慢指针思想。

     快慢指针是指指针移动的步长,快指针移动的快,慢指针移动的慢,例如可以让快指针一次移动两个步长,让慢指针一次移动一个步长。

    快慢指针有两个比较重要的应用:

    1、判断链表是否为单链表

    2、在有序链表中寻找中位数

  • 相关阅读:
    如何将一个HTML页面嵌套在另一个页面中
    error while loading shared libraries: cannot restore segment prot after reloc: Permission denied错误原因[转]
    Sharepoint2007中的甘特图
    在Sharepoint2007新建站点
    开发Sharepoint2007的Webpart备忘
    厦门.NET俱乐部活动和准备Micorsoft TechReadyVisual Studio Team System深度培训有感
    Sharepoint2007中的用户选择器
    User Group Ready To Rock as well
    Sharepoint2007(OSS2007)重新学过
    Sharepoint2007列表中的目录
  • 原文地址:https://www.cnblogs.com/tracyhan/p/5466158.html
Copyright © 2020-2023  润新知