链表的归并排序与链表数组的归并排序

链表的归并排序

就是排序找中点,然后中点位置后一个为null,切断链表,也就是分而治之每次分割一半,一直往后分割,直到只剩下一个节点,或者没有节点停止。

public class ListNode{
        int val;
        ListNode next;

        public ListNode(int x){
            this.val = x;
        }
    }
    public ListNode sortList(ListNode head) {
        // 链表排序
        // 时间复杂度O(nlogn),常数空间复杂度,不能用任何的额外空间
        // 这使用的是归并排序
        // 2-1-4-3 | 1 2 3 4
        if(head == null || head.next == null) return head;
        ListNode fast = head;
        ListNode slow = head;
        while(fast.next!=null && fast.next.next != null){
            slow = slow.next;
            fast = fast.next.next;
        }
        // 获得slow
        ListNode right = sortList(slow.next);
        // 一定要先slow.next = null,否则head找中点会越界
        slow.next = null;
        // 此时被截断成一半
        ListNode left = sortList(head);

        return mergeList(left, right);
    }

    public ListNode mergeList(ListNode left, ListNode right){
        ListNode dummyNode = new ListNode(0);
        ListNode cur = dummyNode;
        while(left != null && right != null){
            if(left.val < right.val){
                cur.next = left;
                left = left.next;
            }else{
                cur.next = right;
                right = right.next;
            }
            cur = cur.next;
        }
        cur.next = left == null ? right : left;
        return dummyNode.next;
    }

链表数组归并排序

可能会含有多个数组,对其归并排序,也是采用找寻终点,但是需要注意,此时找寻的终点,只是数组中的一部分,但是他们都是有结尾null的,所以可以根据index来寻找,跟真实数组的归并排序实质是差不多的,主要是在归并的时候,有使用到递归的操作。

public ListNode mergeKLists(ListNode[] lists) {
        // 使用归并排序
        if (lists == null || lists.length == 0) return lists[0];

        return merge(lists, 0, lists.length - 1);
    }

    public ListNode merge(ListNode[] list, int left, int right){
        // 如果相等,终止条件
        if(left == right) return list[left];
        // 找中点
        int m = left + (right - left)/2;

        ListNode l1 = merge(list,left,m);
        ListNode l2 = merge(list,m+1,right);

        return mergeListNode(l1,l2);
    }

    public static ListNode mergeListNode(ListNode l1, ListNode l2){
        // 递归方式:这里的递归十分精妙!
        if(l1 == null) return l2;
        if(l2 == null) return l1;
        if(l1.val < l2.val){
            l1.next = mergeListNode(l1.next,l2);
            return l1;
        }else{
            l2.next = mergeListNode(l2.next,l1);
            return l2;
        }
    }

递归方式很重要,在二叉树的学习中要更加注意递归方法的学习!加油!

发布了74 篇原创文章 · 获赞 12 · 访问量 8229

猜你喜欢

转载自blog.csdn.net/cao1315020626/article/details/95529405
今日推荐