链表排序

题目

在 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;

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值