排序链表

5 篇文章 0 订阅
4 篇文章 0 订阅

(一)Sort List

https://leetcode.com/problems/sort-list/description/

题目:将链表排序,使得时间复杂度为O(nlogn)

解答:

方法一:归并排序:将链表分成左右两等分,对于每个等分进行递归调用,直到每个等分只含有一个节点;

              第一次犯错:在拆分左右时,忘记将左链表尾部指向null;

代码:

class Solution {
    public ListNode sortList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode mid = findMid(head);
        ListNode right = sortList(mid.next);
        mid.next = null;
        ListNode left = sortList(head);
        return merge(left, right);
    }
    
    private ListNode findMid(ListNode head) {
        ListNode slow = head;
        ListNode fast = head.next;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
    
    private ListNode merge(ListNode head1, ListNode head2) {
        ListNode dummy = new ListNode(0);
        ListNode head = dummy;
        while (head1 != null & head2 != null) {
            if (head1.val < head2.val) {
                head.next = head1;
                head1 = head1.next;
            } else {
                head.next = head2;
                head2 = head2.next;
            }
            head = head.next;
        }
        if (head1 != null) {
            head.next = head1;
        }else {
            head.next = head2;
        }
        return dummy.next;
    }
}

 

方法二:快速排序:找到链表任意节点做pivot,从头到尾依次遍历链表,若节点值小于pivot则连接到left链表,大于则连接到right链表,等于则连接到mid链表。对左、右链表反复进行递归调用,直到链表只含有一个节点或者为空;

代码:

public class Solution {
    public ListNode sortList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode leftDummy = new ListNode(0);
        ListNode leftHead = leftDummy;
        ListNode rightDummy = new ListNode(0);
        ListNode rightHead = rightDummy;
        ListNode midDummy = new ListNode(0);
        ListNode midHead = midDummy;
        ListNode pivot = head;
      
        while (head != null) {
            if (head.val < pivot.val) {
                leftHead.next = head;
                leftHead = leftHead.next;
            } else if (head.val > pivot.val) {
                rightHead.next = head;
                rightHead = rightHead.next;
            } else {
                midHead.next = head;
                midHead = midHead.next;
            }
            head = head.next;
        }
        leftHead.next = null;
        midHead.next = null;
        rightHead.next = null;
        return merge(sortList(leftDummy.next), midDummy.next, sortList(rightDummy.next));
    }
    
    private ListNode merge(ListNode leftHead, ListNode midHead, ListNode rightHead) {
        ListNode dummy = new ListNode(0);
        ListNode head = dummy;
        if (leftHead != null) {
            head.next = leftHead;
            head = findTail(leftHead);
        } 
    
        head.next = midHead;
        head = findTail(midHead);
        head.next = rightHead;
        return dummy.next;
    }
    
    private ListNode findTail(ListNode head) {
        while (head != null && head.next != null) {
            head = head.next;
        }
        return head;
    }
    
}

(二)convert sorted list to binary search tree

https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/description/

题目:将从小到大有序排列的链表转变成二叉搜索树;

解答:找到链表的中间节点作为根,左边发展为左子树,右边发展为右子树。递归调用主函数。

第一次犯错:在拆分左右链表时,忘记把中间点(root)从左链表中去除;

代码:

class Solution {
    public TreeNode sortedListToBST(ListNode head) {
        if (head == null) {
            return null;
        } else if (head.next == null) {
            return new TreeNode(head.val);
        }
        
        ListNode mid = findMid(head);
        TreeNode root = new TreeNode(mid.val);
        ListNode right = mid.next;
        ListNode left = splitLeft(head, mid);
        root.left = sortedListToBST(left);
        root.right = sortedListToBST(right);
        return root;
    }
    
    private ListNode findMid(ListNode head) {
        ListNode slow = head;
        ListNode fast = head.next;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
    
    //split the left part of root (exclude root)
    private ListNode splitLeft (ListNode head, ListNode mid) {
        if (head == mid) {
            return null;
        }
        ListNode res = head;
        while (head != mid && head.next != mid) {
            head = head.next;
        }
        head.next = null;
        return res;
    } 
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值