(一)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;
}
}