# LeetCode 148. Sort linked list

Posted by F.Danials on Mon, 14 Feb 2022 09:01:46 +0100

# subject

Example 1: ```Input: head = [4,2,1,3]
Output: [1,2,3,4]
```

Example 2: ```Input: head = [-1,5,3,4,0]
Output: [- 1,0,3,4,5]
```

Example 3:

```Input: head = []
Output: []
```

Tips:

• The number of nodes in the linked list is in the range [0, 5 * 104]
• -105 <= Node.val <= 105

Advanced: can you sort the linked list under O(n log n) time complexity and constant space complexity?

It is still difficult to sort the linked list. Here is an idea: first traverse the linked list to get the number of elements, then apply for the space of the corresponding number with malloc, store all the linked list elements in the applied array, and sort the array with some sorting methods (fast sorting, Hill sorting, heap sorting, etc.), Then write the ordered data back to the linked list.

Here I do not use the above ideas, but directly operate the linked list, so as to achieve the purpose of ranking the linked list. Both recursive and non recursive code ideas are merge sorting.

# recursion

## thinking

1. Find the midpoint of the linked list, take the midpoint as the boundary, and split the linked list into two sub linked lists.

2. Sort the two sub linked lists separately.

3. Merge the two sorted sub linked lists to obtain a complete sorted linked list.

The above process can be implemented recursively. The termination condition of recursion is that the number of nodes in the linked list is less than or equal to 1, that is, when the linked list is empty or the linked list contains only 1 node, there is no need to split and sort the linked list.

The fast and slow pointer can be used to find the midpoint of the linked list. The fast pointer moves 2 steps at a time and the slow pointer moves 1} step at a time. When the fast pointer reaches the end of the linked list, the linked list node pointed to by the slow pointer is the midpoint of the linked list.

Merging two linked lists can use the tail insertion method to continuously tail the nodes after the given header.

## code

```struct ListNode* Mergedata(struct ListNode* head1,struct ListNode* head2){//Merge two ordered linked lists
}else{
}
cur=cur->next;
}
}else{
}
return s.next;
}
//Find the middle node of the linked list and return the address. Note that this function will divide a linked list into two.
struct ListNode* prev=NULL;
while(fast&&fast->next){
prev=slow;
slow=slow->next;
fast=fast->next->next;
}
prev->next=NULL;
return slow;
}
}
cur=sortList(cur);//Put the second half in order
return Mergedata(head,cur);//Merge the front and rear parts
}``` After reading the above code and using recursion, you will find that this problem is actually the integration of merging two ordered linked lists, finding the middle node of the linked list and merging and sorting.

## Complexity analysis

Time complexity: merge and sort. The time complexity is O(NlogN).

Spatial complexity: the recursion depth is logN, so the spatial complexity is O(logN).

# non-recursive

Because the space complexity of the advanced problem is O(1), it is obvious that the above recursive code does not meet the requirements. Then we need to find a way to turn recursion into a loop.

## thinking

First get the length len of the linked list, and then split the linked list into sub linked lists for merging.

The specific methods are as follows:

1. Use step to represent the length of the sub linked list to be sorted each time. Initially, step=1;

2. Each time, the linked list is divided into several sub linked lists with the length of step (the length of the last sub linked list can be less than step), and each two sub linked lists are combined in a group. After the combination, several ordered sub linked lists with the length of 2*step can be obtained (the length of the last sub linked list can be less than 2*step).

3. Double the value of step, repeat step 2, and merge the longer ordered sub linked list until the length of the ordered sub linked list is greater than or equal to len, and the whole linked list is sorted.

## code

```/**
* struct ListNode {
*     int val;
*     struct ListNode *next;
* };
*/
struct ListNode s;
struct ListNode* cur=&s;
}else{
}
cur=cur->next;
}
}else{
}
return s.next;
}
struct ListNode* Disconnect(struct ListNode* head,int step){
//Split the linked list according to the length of step and return the address of the remaining part after splitting
return NULL;
}
}
cur->next=NULL;
}
int count=0;
count++;
}
return count;
}
struct ListNode s;//Given node, convenient tail insertion
struct ListNode* cur=&s;//Point to the given header node
for(int step=1;step<len;step*=2){//Step < len, merge and sort continue
cur=&s;//Update cur
struct ListNode* h1=head;//Get the first part after splitting
struct ListNode* h2=Disconnect(h1,step);//Get the second part after splitting
cur->next=Mergedata(h1,h2);//Merge the first and second parts and insert them after s
while(cur->next){//cur go ahead for the next tail insertion
cur=cur->next;
}
}
}
return s.next;
}``` ## Complexity analysis

Time complexity: merge and sort. The time complexity is O(NlogN).

Space complexity: no additional space is applied, and the space complexity is O(1).