题目:
Sort a linked list in O(n log n) time using constant space complexity.
思路:
- 因为题目要求O(n log n),在wiki上看了一下各个排序的复杂度,最后选择了归并排序(MergeSort)
- 在wiki上了解了一下归并算法的思想。
- 归并算法建立在归并操作的基础之上
- 归并操作是将两个排好序的序列合并成一个排好序的序列(具体算法看wiki上mergesort词条)
- 利用分治思想,将整个序列等分成两个子序列(若为奇数,有一边长度会多1)
- 这里,我先统计了list的长度len
- 然后在len/2的地方(即左边子序列的尾部),将下一个节点作为右边子序列的头结点rhead
- 令左边子序列尾部指向null,左边子序列头结点lhead指向原来的head
- 则原来的list分开成两个lists,分别以lhead和rhead开头
- 递归地,将两个子序列分别进行归并排序
- 将排好序的两个子序列进行合并操作成一个序列
- 这里用了一个小技巧
- 先让head指向随便一个新建的ListNode节点
- 等归并操作结束后,令head = head.next,则让head还原成真正的第一个节点
- 这样避免了,必须先从两个子序列中找出最小的node赋给head
注意点:
- 内部类不能创建实例
- 需要自建一个ListNode类作链表节点
- 刚开始把ListNode建在类中作为内部类,发现不能建实例(即ListNode head = new ListNode(0) 不成功)
- 后来只能把ListNode单独建一个类调用
- ListNode判断为空的方式
- 不能直接作为boolean判断,即将设有ListNode型head,用if(head)判断head是否为空是不对的
- 只能用if(head!=null)来判断
代码:
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode sortList(ListNode head) {
ListNode l = head;
int len;
for (len = 0; l != null; len++) {
// compute the length of the list
l = l.next;
}
if (len <= 1) {
// if the list is null or has only one node, return the list
return head;
}
ListNode lhead, rhead, temp;
temp = head;
// divide the list into two half ones
for (int i = 1; i < len / 2; i++) {
temp = temp.next;
}
rhead = temp.next;
temp.next = null;
lhead = head;
lhead = sortList(lhead);
// sort the left sub-list and right sub-list recursively
rhead = sortList(rhead);
// merge the sorted left sub-list and right sub-list into one sorted list
head = merge(lhead, rhead);
return head;
}
static ListNode merge(ListNode lhead, ListNode rhead) {
ListNode head, temp;
head = new ListNode(0);//let head initially be an any ListNode node
temp = head;//temp tags the end of the list
while (lhead != null && rhead != null) {
if (lhead.val < rhead.val) {
temp.next = lhead;
lhead = lhead.next;
temp = temp.next;
temp.next = null;
} else {
temp.next = rhead;
rhead = rhead.next;
temp = temp.next;
temp.next = null;
}
}
if (lhead != null) {
temp.next = lhead;
} else {
temp.next = rhead;
}
head = head.next;//let head be the real first node of the list
return head;
}
}