125 lines
3.4 KiB
Markdown
125 lines
3.4 KiB
Markdown
# Leetcode Reverse-Linked-List
|
|
|
|
#### 2022-06-15 22:07
|
|
|
|
---
|
|
##### Algorithms:
|
|
#algorithm #recursion #iteration
|
|
##### Data structures:
|
|
#DS #linked_list
|
|
##### Difficulty:
|
|
#leetcode #coding_problem #difficulty-medium
|
|
##### Lists:
|
|
#CS_list_need_understanding #CS_list_need_practicing
|
|
##### Related topics:
|
|
```expander
|
|
tag:#linked_list
|
|
```
|
|
|
|
- [[Floyd's Cycle Finding Algorithm]]
|
|
- [[Leetcode Linked-List-Cycle]]
|
|
- [[Leetcode Merge-Two-Sorted-Lists]]
|
|
- [[Leetcode Remove-Linked-List-Elements]]
|
|
- [[Two pointers approach]]
|
|
|
|
|
|
|
|
|
|
##### Links:
|
|
- [Link to problem](https://leetcode.com/problems/reverse-linked-list/)
|
|
___
|
|
### Problem
|
|
Given the `head` of a singly linked list, reverse the list, and return _the reversed list_.
|
|
#### Examples
|
|
**Example 1:**
|
|
|
|
![](https://assets.leetcode.com/uploads/2021/02/19/rev1ex1.jpg)
|
|
|
|
```markdown
|
|
**Input:** head = [1,2,3,4,5]
|
|
**Output:** [5,4,3,2,1]
|
|
```
|
|
|
|
**Example 2:**
|
|
|
|
![](https://assets.leetcode.com/uploads/2021/02/19/rev1ex2.jpg)
|
|
|
|
```markdown
|
|
**Input:** head = [1,2]
|
|
**Output:** [2,1]
|
|
```
|
|
|
|
**Example 3:**
|
|
|
|
```markdown
|
|
**Input:** head = []
|
|
**Output:** []
|
|
```
|
|
|
|
#### Constraints
|
|
- The number of nodes in the list is the range `[0, 5000]`.
|
|
- `-5000 <= Node.val <= 5000`
|
|
|
|
### Thoughts
|
|
|
|
I thought a slow O(n ^ 2) hybrid solution, while there are better algorithms, using in-place insert, or recursion.
|
|
|
|
The in place insert is easier to understand, and simple to implement, using a very clever trick.
|
|
|
|
> [!summary] My thoughts on the recursion algorithm
|
|
> #### How was that implemented?
|
|
> The recursion algorithm takes the advantage of the fact that when you change the node's next properties or nodes after that, the node before still points to the same node, so when every node after **tmp** is reversed, simply move **tmp** after **tmp->next**, which now points to the tail of reversed list
|
|
> #### Why return the last element of the original list?
|
|
> It returns the last element in the original list to make sure you are always returning the head of the reversed array, since for any reversed list, the last one comes first.
|
|
|
|
### Solution
|
|
I've referred to this guy: https://leetcode.com/problems/reverse-linked-list/discuss/58130/C%2B%2B-Iterative-and-Recursive
|
|
|
|
This code is hard to understand.
|
|
==TODO==: Make my own version
|
|
```cpp
|
|
class Solution {
|
|
public:
|
|
ListNode *reverseList(ListNode *head) {
|
|
ListNode *pre = new ListNode(0), *cur = head;
|
|
// pre is before head, and insert any element after pre.
|
|
pre->next = head;
|
|
while (cur && cur->next) {
|
|
// temp points to head
|
|
ListNode *temp = pre->next;
|
|
// Move cur->next after pre.
|
|
pre->next = cur->next;
|
|
// Fix pointers, because cur->next is unchanged when changing position.
|
|
cur->next = cur->next->next;
|
|
pre->next->next = temp;
|
|
}
|
|
return pre->next;
|
|
}
|
|
};
|
|
```
|
|
|
|
Recursion:
|
|
==TODO== Needs revision!
|
|
```cpp
|
|
class Solution {
|
|
public:
|
|
ListNode *reverseList(ListNode *head) {
|
|
// Base case: reached the end of list
|
|
if (!head || !(head->next)) {
|
|
return head;
|
|
}
|
|
|
|
// node is the end of the initial linked list, which stays the same
|
|
ListNode *node = reverseList(head->next);
|
|
|
|
// move head after head->next
|
|
// notice that the node before head still points to head!
|
|
head->next->next = head;
|
|
|
|
// since the order is reversed, head->next now points to the tail of the linked list. This is the genius part of this algorithm
|
|
head->next = NULL;
|
|
|
|
return node;
|
|
}
|
|
};
|
|
``` |