Leetcode Sort List ,本算法为进行链表排序,本题提供两种解法,其中解法一是符合题目要求的,如下:
解法一:使用归并排序,使用O(nlg n)时间,O(1)空间,实现时,需要特别注意,我们是在链表上操作,因此除了操作部分,链表也不能与前后两部分断开,相关代码如下:
#include<iostream>
#include<vector>
/*
* There used the merge sort algorithm to sort the linked list, and the
* time using is O(nlg(n)) and the space using is O(1)
*/
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode* sortList(ListNode* head) {
ListNode* cur = head;
int count = 0;
// Count the length of the linked list
while (cur) {
count ++;
cur = cur->next;
}
// Insert an empty node for convenient
ListNode* tmp = new ListNode(0);
tmp->next = head;
head = tmp;
// Record the two parts of the merge process
ListNode* merge_one = NULL;
ListNode* merge_two = NULL;
ListNode* pre = NULL;
ListNode* end = NULL;
// Meger the linked list lg(n) times
for (int i = 1; i < count * 2; i *= 2) {
pre = head;
for (int j = 0; j < count; j += i * 2) {
merge_one = pre->next;
merge_two = pre->next;
int k = i;
for (; k > 0 && merge_two->next; k --) {
merge_two = merge_two->next;
}
// If the second part doesn't exist, just continue
if ((merge_two->next == NULL && k != 0) || merge_two == NULL) {
continue;
}
// Merge the two parts
pre = mergeList(merge_one, merge_two, i, pre);
}
}
return head->next;
}
ListNode* mergeList(ListNode*& one, ListNode*& two, int length, ListNode* pre) {
int count_one = 0;
int count_two = 0;
ListNode* cur = pre;
// Merge the two parts
while (count_one < length && count_two < length && two) {
if (one->val > two->val) {
cur->next = two;
cur = cur->next;
two = two->next;
count_two ++;
} else {
cur->next = one;
cur = cur->next;
one = one->next;
count_one ++;
}
}
ListNode* temp;
// If the first part left, just append it to the list
if (count_one < length) {
temp = one;
cur->next = one;
while (count_one < length) {
temp = one;
one = one->next;
count_one ++;
}
// Link the new list with the left nodes
temp->next = two;
return temp;
}
// If the second part left, just append it to the list
if (two && count_two < length) {
temp = two;
cur->next = two;
while (count_two < length && two) {
temp = two;
two = two->next;
count_two ++;
}
return temp;
}
return NULL;
}
};
// Sample input: ./a.out argv1 argv2 ...
int main(int argc, char* argv[]) {
Solution so;
vector<string> test;
ListNode* head = NULL;
ListNode* cur = NULL;
// Make the test linked list
for (int i = 1; i <argc; i ++) {
if (cur) {
cur->next = new ListNode(atoi(argv[i]));
cur = cur->next;
} else {
cur = new ListNode(atoi(argv[i]));
head = cur;
}
}
head = so.sortList(head);
cur = head;
while (cur) {
cout<<cur->val<<" ";
cur = cur->next;
}
cout<<endl;
return 0;
}
解法二:使快速排序一样的方法,不过此方法需要进行递归,不符合题目要求,但是时间复杂度也为O(nlg n),相关代码如下:
#include<iostream>
#include<vector>
/*
* There used the quik sort algorithm,
*/
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode* sortList(ListNode* head) {
if (!head) {
return head;
}
// Insert an empty node for the convenient
ListNode* tmp = new ListNode(0);
tmp->next = head;
head = tmp;
sort(head, NULL);
return head->next;
}
void sort(ListNode* head, ListNode* end) {
if (!head->next || head->next == end) {
return;
}
ListNode* anchor = head->next;
ListNode* cur = head->next->next;
ListNode* pre = head->next;
// Move the node less than ahead, and left the equal or greater than
while (cur != end) {
if (cur->val < anchor->val) {
pre->next = cur->next;
cur->next = head->next;
head->next = cur;
cur = pre->next;
} else {
pre = cur;
cur = cur->next;
}
}
// Sort the first part
sort(head, anchor);
// Sort the second part
sort(anchor, end);
}
};
// Sample input: ./a.out argv1 argv2 ...
int main(int argc, char* argv[]) {
Solution so;
vector<string> test;
ListNode* head = NULL;
ListNode* cur = NULL;
for (int i = 1; i <argc; i ++) {
if (cur) {
cur->next = new ListNode(atoi(argv[i]));
cur = cur->next;
} else {
cur = new ListNode(atoi(argv[i]));
head = cur;
}
}
head = so.sortList(head);
cur = head;
while (cur) {
cout<<cur->val<<" ";
cur = cur->next;
}
cout<<endl;
return 0;
}