LeetCode-Sort List-鏈表排序-歸併排序+鏈表調整

https://oj.leetcode.com/problems/sort-list/
實現至關麻煩的一道題。主要思想是從中間分開,而後就地的歸併排序兩段子鏈表。函數

比較麻煩的地方有三處:指針

1)注意子鏈表排序後,首尾都發生了變化,因此在排序後須要返回新的首尾。code

2) Merge函數內部也須要調整外面首尾的指針,並返回新的首尾指針。blog

3)Merge函數的兩個邊界狀況是隻有兩個結點。排序

總之這道題想在短期內寫對很是困難。能一次寫出bug-free更是困難。leetcode

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
typedef pair<ListNode *,ListNode *> scpair;
class Solution {
public:
	int n,m;
	scpair Merge(ListNode *hh,ListNode *ee,ListNode *h1,ListNode *t1){
		ListNode *p=h1;
		ListNode *lp=hh;
		ListNode *q=t1->next;
		scpair res=scpair(h1,t1);
		if (h1==t1){
			while(q!=ee){
				if (p->val<=q->val) break;
				if (lp!=NULL) lp->next=q;
				p->next=q->next;
				q->next=p;
				if (lp==hh) res.first=q;
				lp=q;
				q=p->next;
			}
			p=res.first;
			while(p!=ee){
				res.second=p;
				p=p->next;
			}
			return res;
		}
		res.first=h1;
		while(q!=ee && p!=ee && p!=q){
			if (p->val<q->val){
				lp=p;
				p=p->next;
			}
			else{
				t1->next=q->next;
				q->next=p;
				if (lp!=NULL) lp->next=q;
				if (lp==hh) res.first=q;
				lp=q;
				q=t1->next;
			}
		}
		p=res.first;
		while(p!=ee){
			res.second=p;
			p=p->next;
		}
		return res;
	}
	scpair MSort(ListNode *hh,ListNode *ee,ListNode *h,ListNode *t,int num){
		if (h==t){return scpair(h,t);}
		ListNode *h1=h;
		ListNode *t1=h;
		int count=1;
		while(count<num/2){
			t1=t1->next;
			count++;
		}
		ListNode *h2=t1->next;
		ListNode *t2=t;
		scpair l=MSort(hh,h2,h1,t1,count);
		scpair r=MSort(l.second,ee,h2,t2,num-count);
		scpair res=Merge(hh,ee,l.first,l.second);
		return res;
	}
	ListNode *sortList(ListNode *head) {
		if (head==NULL){return NULL;}
		ListNode *p=head;
		ListNode *q=p;
		n=1;
		while (p->next!=NULL){
			q=p;
			p=p->next;
			n++;
		}
		if (p==q){return head;}
		scpair res=MSort(NULL,NULL,head,p,n);
		return res.first;
	}
};
相關文章
相關標籤/搜索