快排和归并排序链表

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35508033/article/details/88997594

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

归并排序

归并排序应该算是链表排序最佳的选择了,保证了最好和最坏时间复杂度都是nlogn,而且它在数组排序中广受诟病的空间复杂度在链表排序中也从O(n)降到了O(1)。

归并排序的一般步骤为:

  1. 将待排序数组(链表)取中点并一分为二;
  2. 递归地对左半部分进行归并排序;
  3. 递归地对右半部分进行归并排序;
  4. 将两个半部分进行合并(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;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_35508033/article/details/88997594