版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35508033/article/details/88997594
https://leetcode-cn.com/problems/sort-list/
归并排序
归并排序应该算是链表排序最佳的选择了,保证了最好和最坏时间复杂度都是nlogn,而且它在数组排序中广受诟病的空间复杂度在链表排序中也从O(n)降到了O(1)。
归并排序的一般步骤为:
- 将待排序数组(链表)取中点并一分为二;
- 递归地对左半部分进行归并排序;
- 递归地对右半部分进行归并排序;
- 将两个半部分进行合并(merge),得到结果。
首先用快慢指针(快慢指针思路,快指针一次走两步,慢指针一次走一步,快指针在链表末尾时,慢指针恰好在链表中点)的方法找到链表中间节点,然后递归的对两个子链表排序,把两个排好序的子链表合并成一条有序的链表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode sortList(ListNode head) {
if(head==null||head.next==null){
return head;
}
ListNode mid=getMid(head);
ListNode right=mid.next;
mid.next=null;//断链
return mergeSort(sortList(head),sortList(right));
}
//获取链表的中间结点,偶数时取中间第一个
private ListNode getMid(ListNode head){
if(head==null||head.next==null){
return head;
}
ListNode slow=head,fast=head;
while(fast.next!=null&&fast.next.next!=null){
slow=slow.next;
fast=fast.next.next;
}
return slow;
}
//递归归并两个有序链表
private ListNode mergeSort(ListNode l1, ListNode l2) {
ListNode res = null;
if (l1 == null){
return l2;
}
if (l2 == null){
return l1;
}
if (l1.val <= l2.val) {
res = l1;
l1.next = mergeSort(l1.next, l2);
} else {
res = l2;
l2.next = mergeSort(l1, l2.next);
}
return res;
}
}
快速排序
在一般实现的快速排序中,我们通过首尾指针来对元素进行切分,下面采用快排的另一种方法来对元素进行切分。
我们只需要两个指针p1和p2,这两个指针均往next方向移动,移动的过程中保持p1之前的key都小于选定的key,p1和p2之间的key都大于选定的key,那么当p2走到末尾时交换p1与key值便完成了一次切分。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode sortList(ListNode head) {
quickSort(head,null);
return head;
}
private void quickSort(ListNode head,ListNode end){
if(head!=end){
ListNode node=patrtion(head,end);
quickSort(head,node);
quickSort(node.next,end);
}
}
private ListNode patrtion(ListNode head,ListNode end){
ListNode p1=head,p2=head.next;
while(p2!=end){
//小于key值时,p1向前走一步,交换p1与p2的值
if(p2.val<head.val){
p1=p1.next;
int temp=p1.val;
p1.val=p2.val;
p2.val=temp;
}
p2=p2.next;
}
//当有序时,不交换p1和key值
if(p1!=head){
int temp=p1.val;
p1.val=head.val;
head.val=temp;
}
return p1;
}
}