链表排序

来源:互联网 发布:算法经典书籍 编辑:程序博客网 时间:2024/06/09 23:56

题目

在 O(n log n) 时间复杂度和常数级的空间复杂度下给链表排序。

您在真实的面试中是否遇到过这个题? Yes
样例
给出 1->3->2->null,给它排序变成 1->2->3->null.

解题

尝试快速排序,划分节点不知道怎么找
参考链接
快速排序
找到小于x,找到等于x,找到大于x,三个链表合并
注意:
如果小于x和等于x的在一起考虑,有错误
如:1 3 2
第一次划分 成1 和3 2
3 2 始终 是划分在一起,出现栈溢出

/** * Definition for ListNode. * public class ListNode { *     int val; *     ListNode next; *     ListNode(int val) { *         this.val = val; *         this.next = null; *     } * } */ public class Solution {    /**     * @param head: The head of linked list.     * @return: You should return the head of the sorted linked list,                    using constant space complexity.     */    public ListNode sortList(ListNode head) {          // write your code here        if(head == null)            return head;        ListNode sortList = quickSort(head);        return sortList;    }    public ListNode quickSort(ListNode head){        if(head==null || head.next==null)            return head;        ListNode lowHead = new ListNode(0);        ListNode low = lowHead;        ListNode highHead = new ListNode(0);        ListNode high = highHead;        ListNode midHead = new ListNode(0);        ListNode mid = midHead;        ListNode p = head;        int x = p.val;        while(p!=null){            if(p.val <x){                low.next = p;                low = low.next;            }else if(p.val >x){                high.next = p;                high = high.next;            }else{                mid.next = p;                mid = mid.next;            }            p = p.next;        }        low.next = null;// 断开        mid.next = null;        high.next = null;        ListNode l1 = quickSort(lowHead.next);        ListNode l2 = quickSort(highHead.next);        ListNode merge = concat(l1,midHead.next,l2);        return merge;    }    public ListNode concat(ListNode low,ListNode mid,ListNode high){        ListNode lowLast = getLastNode(low);        ListNode midLast = getLastNode(mid);        if(low==null){            midLast.next = high;            return mid;        }        lowLast.next = mid;        midLast.next = high;        return low;    }    public ListNode getLastNode(ListNode head){        if(head ==null)            return head;        ListNode last = head;        while(last.next!=null){            last = last.next;        }        return last;    }}

上面链接中给了归并排序算法

    public ListNode mergeSort(ListNode head){        if(head == null || head.next == null)            return head;        ListNode mid = findMiddle(head);        ListNode right = sortList(mid.next); // 先右边排序         mid.next = null;// 断开        ListNode left = sortList(head);        return merge(left, right);    }    private ListNode merge(ListNode head1, ListNode head2) {        ListNode dummy = new ListNode(0);        ListNode tail = dummy;        while (head1 != null && head2 != null) {            if (head1.val < head2.val) {                tail.next = head1;                head1 = head1.next;            } else {                tail.next = head2;                head2 = head2.next;            }            tail = tail.next;        }        if (head1 != null) {            tail.next = head1;        } else {            tail.next = head2;        }        return dummy.next;    }    public ListNode findMiddle( ListNode head){        ListNode slow = head;        ListNode fast = head;        while(fast!=null && fast.next!=null && fast.next.next!=null){            slow = slow.next;            fast = fast.next.next;        }        return slow;    }

桶排序
min - max之间的数转化成a - b 之间的方式
一般归一化的方式:maxvalmaxmin
可以发现:min转化成 1 ,max转化成 0
下面需要将其转化到:a-b之间
一般认为是这样转化:
a+rand(0,1)(ba),这里的rand就是上面的归一化方式
但是还是会发现max转化成最小值,min转化成最大值
桶排序要使较大的数放在大桶号,较小的数放在小桶号
上面等式还需要改变
brand(0,1)(ba)
这样就好了

public class Solution {    /**     * @param head: The head of linked list.     * @return: You should return the head of the sorted linked list,                    using constant space complexity.     */    public ListNode sortList(ListNode head) {          // write your code here        if(head == null)            return head;        ListNode sortList = bucketSort(head);        return sortList;    }        public ListNode bucketSort(ListNode head){        if(head == null || head.next == null)            return head;        int min = getMin(head);        min = min>0?min:0;        int max = getMax(head);        max = max>0?max:0;        int N = 14;        int a = 0;        int b = N-1;        ListNode[] bucket = new ListNode[N];        for(int i=0;i<N;i++){            bucket[i] = new ListNode(0);        }        ListNode p = head;        while(p!=null){            int val  = p.val;            int index = val%N;            ListNode pNext = p.next;            if(val<0)                index =0;            else{                index = b - (b-a)*(max - val)/(max - min);            }            insertList(bucket[index],p);            p = pNext;        }        ListNode sortHead = new ListNode(0);        ListNode cur = sortHead;        for(int i=0;i<N;i++){            ListNode bk = bucket[i].next;            while(bk!=null){                cur.next = bk;                cur = cur.next;                bk = bk.next;            }        }        return sortHead.next;    }    public int getMax(ListNode head){        ListNode p = head;        int max = p.val;        while(p!=null){            max = max<p.val?p.val:max;            p = p.next;        }        return max;    }    public int getMin(ListNode head){        ListNode p = head;        int min = p.val;        while(p!=null){            min = min>p.val?p.val:min;            p = p.next;        }        return min;    }     // 有头节点的插入     public void insertList(ListNode head,int val){        ListNode insertNode = new ListNode(val);        insertNode.next =null;        ListNode prev = head;        // 插入在头        if(prev.next==null){            prev.next = insertNode;            return;        }        // 插入在中间        while(prev.next!=null){            if(prev.next.val<=val){                prev = prev.next;            }else{                insertNode.next = prev.next;                prev.next = insertNode;                return;            }        }        // 插入在末尾         prev.next = insertNode;    }   // 有头节点的插入     public void insertList(ListNode head,ListNode o){        ListNode insertNode = o;        ListNode prev = head;        if(prev.next==null){            prev.next = insertNode;            prev = prev.next;            prev.next =null;            return;        }        int val = insertNode.val;        while(prev.next!=null){            if(prev.next.val<=val){                prev = prev.next;            }else{                insertNode.next = prev.next;                prev.next = insertNode;                return;            }        }        // 插入在末尾         prev.next = insertNode;        prev = prev.next;        prev.next =null;    }}
0 0