LeetCode HOT 100 —— 148.排序链表

题目

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
LeetCode HOT 100 —— 148.排序链表_第1张图片
LeetCode HOT 100 —— 148.排序链表_第2张图片

进阶:你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?

思路

题目要求时间空间复杂度分别为O(nlogn)和O(1),根据时间复杂度不难想到二分法,从而想到归并排序

通过递归实现链表归并排序,主要有两个过程:

  • 分割过程:找到当前链表中点,断开,可以采用快慢指针法,奇数个节点找到中点,偶数个节点找到中心左边的节点
  • 合并过程:将两个排序链表合并,转化成一个排序链表,使用双指针法合并,分别比较两个指针处节点值大小,按从小到大的顺序插入链表

LeetCode HOT 100 —— 148.排序链表_第3张图片
java代码如下:

class Solution{//先分,再排序,最后合并
	public ListNode sortList(ListNode head){
		if (head == null || head.next == null)
			return head;
		
		//快慢指针找链表中点
		ListNode slow = head;
		ListNode fast = head.next;//这里fast要后移一位,因为如果是偶数位,我们找的是中心点的左边一个节点,因为这样方便判断边界,即slow即为上个区间的最后一个节点,如果不后移找到的就是中心点右边的节点,不方便划分区间,自己画个图走一遍就知道了
		while (fast != null && fast.next != null) {
			slow = slow.next;
			fast = fast.next.next;
		} 
		ListNode tmp = slow.next;//记录下个区间的起始边界位置
		slow.next = null;//断开链表,分成两个区间链表
		ListNode left = sortList(head);//排序左区间链表
		ListNode right = sortList(tmp);//排序右区间链表
		ListNode dummy = new ListNode(0);//创建虚拟头结点,用于最后返回结果
		ListNode h = dummy;//移动指针,用于添加节点
		
		//合并两个有序链表
		while (left != null && right != null) {//只要两个链表都不为空
			if (left.val < right.val) {//分别比较两个链表的节点值大小并加入	
				h.next = left;//将小的节点加入结果链表
				left = left.next;//同时指针后移
			} else {
				h.next = right;
				right = right.next;
			}
			h = h.next;//加入完节点后,结果链表中的指针后移,方便继续添加后续节点
		}
		h.next = (left != null ? left : right);//如果有链表没有加入完毕,则直接加入剩下非空的节点
		return dummy.next;//返回结果链表
	}
}

你可能感兴趣的:(LeetCode,热题,HOT,100,链表,leetcode,数据结构)