leetcode——链表排序(归并排序)

归并排序
(1)待排序的数组、链表从中间一分为二
(2)递归将左半部分进行归并排序
(3)递归将右半部分进行归并排序
(4)将左半部分和右半部分进行有序合并

  • 分割次数 = log2^n
  • 时间复杂度O(nlogn)
  • 空间复杂度O(n)

题目
在O(nlogn)的时间内使用常数级空间复杂度对链表进行排序。

解析
时间复杂度为O(nlogn)的排序算法有归并排序和快排
归并排序的空间复杂度为O(n),快排的空间复杂度为O(1),此处采用归并排序
使用快慢指针找到中间节点

代码

/**
 * 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) {
    
    
	      //如果链表为空或者只有一个节点,直接返回该链表
	      if(head==null || head.next==null) return head;
	     
	     //获取中间节点
	     ListNode mid = getMid(head);
	     //分为左右两部分
	     ListNode right = mid.next;
	     ListNode left = head;
	    
	     //对左右部分进行有序合并
	     return Merge(sortList(left),sortList(right));
    }

    //利用快慢指针找中间节点
    public ListNode getMid(ListNode head){
    
    
	      if(head==null || head.next==null) return head;
	    
	      ListNode slow = head;
	      ListNode quick = head;
	      while(quick.next!=null&&quick.next.next==null){
    
    
		      slow = slow.next;
		      quick = quick.next.next;
	      }
	      return slow;
    }
   
   //两个有序链表的合并
   public ListNode Merge(ListNode h1,ListNode h2){
    
    
	   if(h1==null) return h2;
	   if(h2==null) return h1;
	
	   //新链表的头结点
	   ListNode head = new ListNode(0);
	   //当前结点
	   ListNode current = head;
	   while(h1!=null&&h2!=null){
    
    
		   if(h1.val>h2.val){
    
    
			   current.next = h2;
			   h2 = h2.next;
		   }else{
    
    
			   current.next = h1;
			   h1 = h1.next;
		   }
		   current = current.next;
	   }
	   //去掉头结点
	   return head.next;
   }
}

猜你喜欢

转载自blog.csdn.net/weixin_42937036/article/details/105345396
今日推荐