欧美1区2区3区激情无套,两个女人互添下身视频在线观看,久久av无码精品人妻系列,久久精品噜噜噜成人,末发育娇小性色xxxx

題解 | #單鏈表的排序#堆排序最簡(jiǎn)單而直接

默認(rèn)你已經(jīng)理解題意

思路如下

堆排序-簡(jiǎn)單直接

  1. 定義類(lèi)型為L(zhǎng)istNode的最小堆
  2. 建堆:鏈表所有node入堆
  3. 依次彈出堆頂node,即是從小到大的順序
  4. 時(shí)間復(fù)雜度O(nlogn),空間復(fù)雜度O(n)
  5. 此法和數(shù)組的堆排序幾乎沒(méi)有區(qū)別,實(shí)現(xiàn)起來(lái)最簡(jiǎn)單,不易出錯(cuò)
class Solution {
    public ListNode sortList(ListNode head) {
        PriorityQueue<ListNode> heap = new PriorityQueue<ListNode>((a,b)->a.val-b.val);
        while(head!=null)
        {
            heap.offer(head);
            head=head.next;
        }
        ListNode dummy=new ListNode();
        ListNode cur = dummy;
        while(heap.size()>0)
        {
            cur.next=heap.peek();
            heap.poll();
            cur=cur.next;
        }
        cur.next=null;
        return dummy.next;
    }
}

空間復(fù)雜度降低-歸并

  1. 數(shù)組的歸并排序需要引入輔助數(shù)組用于歸并,因此空間復(fù)雜度是O(n)
  2. 有序鏈表的歸并不需要額外空間輔助
  3. 自頂向下,對(duì)鏈表進(jìn)行排序:
  • 若鏈表元素為1或0:
    • 已經(jīng)有序,返回頭結(jié)點(diǎn)
  • 否則
    • 快慢指針?lè)?/strong>將鏈表分為兩部分,其長(zhǎng)度差不超過(guò)1
    • 對(duì)這兩部分鏈表排序(遞歸)
    • 合并排序后的兩個(gè)鏈表
  1. 時(shí)間復(fù)雜度是O(nlogn),空間復(fù)雜度是O(logn),即遞歸調(diào)用的深度
public class Solution {
    public ListNode SortList(ListNode head) {
        if(head==null || head.next==null) return head;
        var secondHead = Split(head);
        head=SortList(head);
        secondHead=SortList(secondHead);
        return Merge(head,secondHead);
    }
    ListNode Merge(ListNode head1, ListNode head2)
    {
        var dummy=new ListNode(0);
        var cur=dummy;
        while(head1!=null&&head2!=null)
        {
            if(head1.val<=head2.val)
            {
                cur.next=head1;
                head1=head1.next;
            }
            else
            {
                cur.next=head2;
                head2=head2.next;
            }
            cur=cur.next;
        }
        if(head1!=null) cur.next=head1;
        else cur.next=head2;
        return dummy.next;
    }
    ListNode Split(ListNode head)
    {
        ListNode slow=head, fast=head.next;
        while(fast!=null&&fast.next!=null)
        {
            slow=slow.next;
            fast=fast.next.next;
        }
        var newHead = slow.next;
        slow.next=null;
        return newHead;
    }
}

空間復(fù)雜度再降低-自底向上的歸并

  1. 熟悉歸并排序的兄弟應(yīng)該知道,若采用自下而上的歸并,可以把遞歸調(diào)用改為迭代的,不使用額外空間

  2. 但是對(duì)于鏈表來(lái)講,可以把只有1個(gè)節(jié)點(diǎn)的鏈表看成有序的,即歸并的底

  3. 兩個(gè)長(zhǎng)度為1的鏈表合并為長(zhǎng)度為2的有序鏈表,那么兩個(gè)長(zhǎng)度為2的鏈表合并為長(zhǎng)度為4的有序鏈表,以此類(lèi)推

  4. 現(xiàn)在我們?cè)O(shè)歸并長(zhǎng)度是len,當(dāng)然一開(kāi)始len=1,每進(jìn)行一輪歸并,len*=2,當(dāng)len>=原始鏈表長(zhǎng)度的時(shí)候,鏈表的排序就完成了

我們曉得鏈表始終不能斷開(kāi)的,所以merge方法中不能用null來(lái)判斷是否合并完一條鏈表

我們把merge方法設(shè)計(jì)成

void Merge(ListNode beforeHead, ListNode mid, ListNode afterTail)

  • beforehead用于確定head1和合并的指針的位置
  • mid是鏈表2的開(kāi)始head2(頭結(jié)點(diǎn)),同時(shí)也是鏈表1的結(jié)尾哨兵
  • afterTail是鏈表2的結(jié)尾哨兵

那如何確定每次合并的3個(gè)參數(shù)?

  • 對(duì)每個(gè)len的首次合并,beforeHead為鏈表頭部之前的哨兵節(jié)點(diǎn)
  • mid為beforeHead后面的第len+1個(gè)節(jié)點(diǎn)
  • afterTail為mid后面的第len個(gè)節(jié)點(diǎn)
  • 使用上述參數(shù)完成一個(gè)區(qū)間的合并
  • 下一個(gè)區(qū)間的beforeHeadbeforeHead后面的第len*2個(gè)節(jié)點(diǎn)
  • 以上移動(dòng)均需注意是否達(dá)到鏈表尾部的null
  • 若beforeHead為null,本輪合并完成

時(shí)間復(fù)雜度是O(nlogn),空間復(fù)雜度是O(1),只使用了幾個(gè)變量和1層函數(shù)調(diào)用

//c#的代碼  
public class Solution {
    public ListNode SortList(ListNode head) {
        if(head==null||head.next==null) return head;
        int n=0;
        ListNode dummy = new ListNode();
        dummy.next=head;
        var cur = head;
        while(cur!=null)
        {
            cur=cur.next;
            n++;
        }
        int len=1;
        while(len<n)
        {
            var beforeHead=dummy;
            while(beforeHead!=null)
            {
                var mid = beforeHead.next;
                for(int i=0;i<len;i++)
                {
                    if(mid!=null) mid=mid.next;
                    else break;
                }
                var afterTail=mid;
                for(int i=0;i<len;i++)
                {
                    if(afterTail!=null) afterTail=afterTail.next;
                    else break;
                }
                Merge(beforeHead,mid,afterTail);
                for(int i=0;i<len*2;i++)
                {
                    if(beforeHead!=null)
                        beforeHead=beforeHead.next;
                    else break;
                }
            }
            len*=2;
        }
        return dummy.next;
    }
    void Merge(ListNode beforeHead, ListNode mid, ListNode afterTail)
    {
        var cur = beforeHead;
        var head1 = cur.next;
        var head2 = mid;
        while(head1!=mid&&head2!=afterTail)
        {
            if(head1.val<=head2.val)
            {
                cur.next=head1;
                head1=head1.next;
            }
            else
            {
                cur.next=head2;
                head2=head2.next;
            }
            cur=cur.next;
        }
        while(head1!=mid)
        {
            cur.next=head1;
            head1=head1.next;
            cur=cur.next;
        }
        while(head2!=afterTail)
        {
            cur.next=head2;
            head2=head2.next;
            cur=cur.next;
        }
        cur.next=afterTail;
    }
}
全部評(píng)論

相關(guān)推薦

D0cC:京東營(yíng)收1萬(wàn)多億人民幣,阿里9000多億,雖然他倆利潤(rùn)都沒(méi)騰訊和字節(jié)多,但是很恐怖了啊,負(fù)擔(dān)了多少打工人的薪水
投遞拼多多集團(tuán)-PDD等公司10個(gè)崗位
點(diǎn)贊 評(píng)論 收藏
分享
被加薪的哈里很優(yōu)秀:應(yīng)該繼續(xù)招人,不會(huì)給你留崗位的
點(diǎn)贊 評(píng)論 收藏
分享
評(píng)論
1
收藏
分享

創(chuàng)作者周榜

更多
??途W(wǎng)
??推髽I(yè)服務(wù)