Using the idea of constant storage space, merge sorting and divide and conquer, the chain list is divided into equal parts until it reaches a single node, and then the chain list is merged and sorted.
The time complexity O(lg2N) is divided equally for the linked list, and the two sorted linked lists are combined. The time complexity O(N), therefore, is O (Nlg2N). The code is as follows.
/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ typedef struct ListNode Node; /* Merge two sort lists */ Node *merge(Node *l1, Node *l2){ Node *head = NULL; Node *rear = NULL; while(l1 && l2){ if(l1->val < l2->val ){ if(!head){ head = l1; }else{ rear->next = l1; } rear = l1; l1 = l1->next; }else{ if(!head){ head = l2; }else{ rear->next = l2; } rear = l2; l2 = l2->next; } } if(l2){ if(head){ rear->next = l2; }else{ head = l2; } } if(l1){ if(head) rear->next = l1; else{ head = l1; } } return head; } /* Divide the linked list into two linked lists from the middle and return to the head of the latter */ Node *get_mid(Node *node){ Node *p = node; Node *mid = node; Node *last_mid = NULL; if(!node || !node->next){ return NULL; } /* Using the fast and slow pointer method, p moves two nodes at a time, and mid moves one node at a time, */ while(p){ p = p->next; if(p) p = p->next; last_mid = mid; mid = mid->next; } /* Truncate the list */ last_mid->next = NULL; return mid; } Node *merge_sort(Node *node){ /* For the return conditions of recursive calls, pay attention to putting the return conditions of recursion at the beginning to judge the most original parameters * If other operations are carried out on the parameters, it may lead to inaccurate conditions. */ if(!node || !node->next){ return node; } /* Split the list in two */ Node *l1 = node; Node *l2 = get_mid(node); /* Recursive sorting of two linked lists */ l1 = merge_sort(l1); l2 = merge_sort(l2); /* Merge two sorted linked lists */ return merge(l1, l2); } struct ListNode* sortList(struct ListNode* head){ return merge_sort(head); }
The second method is to use an array with the same length of list to put all node - > Val addresses into the array, and use fast sorting to sort the array.
Space complexity O(N), time complexity O(N), because the length of list is obtained first.
The code is as follows.
/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ inline void swap(int *a, int *b){ int tmp = *a; *a = *b; *b = tmp; } typedef struct ListNode Node; int get_len(Node *head){ int i=0; Node *p = head; while(p){ p = p->next; i++; } return i; } void sort(int **arr, int start, int end){ if(start >= end){ return; } /* first sort */ /* 8 4 6 7 9 10 */ int temp = *(arr[start]); int i= start; int j= end; while(start < end){ while(start<end && *(arr[end]) >= temp){ end--; } while(start<end && *(arr[start]) <= temp ){ start++; } swap(arr[end], arr[start]); } swap(arr[start], arr[i]); /* and than recure */ sort(arr, i, start); sort(arr, start+1, j); } struct ListNode* sortList(struct ListNode* head){ Node *p = head; int len = get_len(head); if(!len){ return head; } int **arr = (int **)malloc(sizeof(int *) * len); int i=0; while(p){ arr[i++] = &p->val; p = p->next; } sort(arr, 0, len-1); free(arr); return head; }