leetcode刷题5

今天刷的题是LeetCode第148题,难度中等

题目的要求是在O(nlogn)的时间复杂度情况下和常数级的空间复杂度对链表进行排序

一般地数据排序,冒泡、插入和选择排序都是O(N2),而归并排序和快速排序的时间复杂度是O(nlogn)。因此在算法上可以考虑归并排序和快速排序

如果采用一般的上述排序算法,需要O(N)的空间复杂度。因此需要对上述算法进行改进

本文选择的是链表中的归并排序算法。该算法也同样需要对数据进行分割和合并。在分割的时候,是采用的双指针策略。

然后合并操作。合并操作就是比较链表的节点的值。最后返回合并后的链表即可。具体的代码如下所示:

public class SortList {
    public static void main(String[] args) {
        int[] a={-5,-10,-2,1,0,10,12,9,4};
        ListNode head=ListNode.generateListNode(a);
        head=SortList.sort(head);
        while (head!=null){
            System.out.println(head.val);
            head=head.next;
        }
    }
    public static ListNode sort(ListNode head){
        return head==null ? null:SortList.mergeSort(head);
    }
    public static ListNode mergeSort(ListNode head){
        //边界条件
        if (head.next==null)return head;
        //定义双指针,将链表分为两部分
        ListNode fast=head;
        ListNode slow=head;
        ListNode pre=null;
        while (fast!=null && fast.next!=null ){
            pre=slow;
            fast=fast.next.next;
            slow=slow.next;
        }
        pre.next=null;
        ListNode left=head;
        ListNode right=slow;
        ListNode l=mergeSort(left);
        ListNode r=mergeSort(right);
        return merge(l,r);
    }
    public static ListNode merge(ListNode left,ListNode right){
        ListNode result=new ListNode(0);
        ListNode current=result;
        while (left!=null && right!=null){
            if (left.val<right.val){
                current.next=left;
                current=current.next;
                left=left.next;
            }else if (left.val>=right.val){
                current.next=right;
                right=right.next;
                current=current.next;
            }
            if (left!=null){
                current.next=left;
            }if (right!=null){
                current.next=right;
            }
        }
        return result.next;
    }
}

猜你喜欢

转载自www.cnblogs.com/cquer-xjtuer-lys/p/11329293.html
今日推荐