题目链接:https://leetcode-cn.com/problems/sort-list/submissions/
附上具体题目如下:
由于该题目的要求时间复杂度为O(nlogn)以及空间复杂度为O(1)。因此之前的插入排序算法在这道题中不适用,在这道题中我才用归并排序算法,这里有人可能会有人觉得奇怪,因为虽然归并排序算法的时间复杂度是O(nlogn),但是空间复杂度却是O(n),并不是常数级的。
因此这里体现了线性表中数组和链表的区别之处:数组的空间不是动态可变的,而链表却可以动态可变,因此在这道题中只需要改变链表的方向就可以将两个链表合并成一个链表,无需像数组那样重新开辟空间来存储数据。因此链表的合并排序算法的空间复杂度是常数级的。
归并排序的过程主要分为两个过程:分和治。分就是将不断将链表分为两个链表,直到不可分为止;而治就是将排好序后的链表不断合并直到合成一个完整的链表。
由于链表没有随机访问的特性,因此这里使用快慢指针的方法将一个链表一分为二,具体的方法是:使用一个快指针fast和慢指针slow,fast指针每次前进两个结点,slow指针每次前进一个结点。当fast指针不能前进的时候,slow指针是前一个链表的最后一个结点,slow.next指针是第二个链表的首结点。
这里注意分的过程循环条件为:fast.next != null && fast.next.next != null
!!!
具体的java代码实现如下:
class Solution {
public ListNode sortList(ListNode head) {
if(head == null || head.next == null)
return head;
return mergeSort(head);
}
public ListNode mergeSort(ListNode head){
if(head.next == null)
return head;
ListNode fast = head, slow = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
}
ListNode rightHead = slow.next;//第二个链表的头结点
slow.next = null;//断开链表
ListNode left = mergeSort(head);//不断进行分的过程
ListNode right = mergeSort(rightHead);
return merge(left, right);//合并排序后的链表
}
//对两个有序链表进行排序
public ListNode merge(ListNode left, ListNode right){
ListNode head = new ListNode(0);
ListNode temp = head;
while(left != null && right != null){
if(left.val < right.val){
temp.next = left;
temp = temp.next;
left = left.next;
}
else{
temp.next = right;
temp = temp.next;
right = right.next;
}
}
if(left != null)
temp.next = left;
if(right != null)
temp.next = right;
return head.next;
}
}
可运行的java文件:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.List;
import java.util.Iterator;
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public class MainClass {
public ListNode sortList(ListNode head) {
if(head == null || head.next == null)
return head;
return mergeSort(head);
}
public void PrintList(List<int[]> list){
for(int i = 0; i < list.size(); i++)
System.out.println("[" + list.get(i)[0] + "," + list.get(i)[1] + "]");
}
public ListNode mergeSort(ListNode head){
if(head.next == null)
return head;
ListNode fast = head, slow = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
}
ListNode rightHead = slow.next;
slow.next = null;
ListNode left = mergeSort(head);
ListNode right = mergeSort(rightHead);
return merge(left, right);
}
public ListNode merge(ListNode left, ListNode right){
ListNode head = new ListNode(0);
ListNode temp = head;
while(left != null && right != null){
if(left.val < right.val){
temp.next = left;
temp = temp.next;
left = left.next;
}
else{
temp.next = right;
temp = temp.next;
right = right.next;
}
}
if(left != null)
temp.next = left;
if(right != null)
temp.next = right;
return head.next;
}
public static int[] stringToIntegerArray(String input) {
input = input.trim();
input = input.substring(1, input.length() - 1);
if (input.length() == 0) {
return new int[0];
}
String[] parts = input.split(",");
int[] output = new int[parts.length];
for(int index = 0; index < parts.length; index++) {
String part = parts[index].trim();
output[index] = Integer.parseInt(part);
}
return output;
}
public static ListNode stringToListNode(String input) {
// Generate array from the input
int[] nodeValues = stringToIntegerArray(input);
// Now convert that list into linked list
ListNode dummyRoot = new ListNode(0);
ListNode ptr = dummyRoot;
for(int item : nodeValues) {
ptr.next = new ListNode(item);
ptr = ptr.next;
}
return dummyRoot.next;
}
public static String listNodeToString(ListNode node) {
if (node == null) {
return "[]";
}
String result = "";
while (node != null) {
result += Integer.toString(node.val) + ", ";
node = node.next;
}
return "[" + result.substring(0, result.length() - 2) + "]";
}
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = in.readLine()) != null) {
ListNode head = stringToListNode(line);
ListNode ret = new MainClass().sortList(head);
String out = listNodeToString(ret);
System.out.print(out);
}
}
}