自己的做法
算法思想
使用三个指针cur
、pre
和next
,遍历链表。cur
代表当前指向的结点,pre
代表当前cur
的前一个结点,next
代表cur
的后一个结点。
初始时,cur
指向head->next
即链表第二个结点,pre
指向head
,即头结点。next
为空指针。
然后依次执行以下步骤:
next
结点指向cur
的下一个节点
cur
结点的next
指向pre
结点
pre
结点指向cur
结点
cur
指向next
节点
这样就将pre
和cur
指向的结点进行了反转,并指向了下一个要反转的结点。
直到cur
指向了空,此时循环结束,链表反转完成。
注:
算法实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| struct ListNode { int val; ListNode *next; ListNode() : val(0), next(nullptr) {} ListNode(int x) : val(x), next(nullptr) {} ListNode(int x, ListNode *next) : val(x), next(next) {} };
class Solution { public: ListNode* reverseList(ListNode* head) { if(head == nullptr || head->next == nullptr) {return head;}
ListNode * pre = head; ListNode * cur = head->next; ListNode * next = nullptr; while (cur != nullptr) { if(pre == head) { pre->next = nullptr; } next = cur->next; cur->next = pre; pre = cur; cur = next; }
return pre;
} };
|
还有一种更简单的写法,省去了判断链表结点数是否大于等于2和pre == head
的情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class Solution { public: ListNode* reverseList(ListNode* head) { ListNode * pre = nullptr; ListNode * cur = head; ListNode * next = nullptr; while (cur != nullptr) { if(pre == head) { pre->next = nullptr; } next = cur->next; cur->next = pre; pre = cur; cur = next; } return pre;
} };
|
性能分析
时间复杂度为O(n)。
空间复杂度:用了三个指针,O(1)。
官方做法
递归
算法思想
从链表头结点递归到最后一个结点,然后进行回溯,当head
指向一个结点时,要让它的下一个结点指向它,则需要执行head->next->next = head
, 并让head
结点的next
指向空。
代码实现
1 2 3 4 5 6 7 8 9 10 11 12
| class Solution { public: ListNode* reverseList(ListNode* head) { if(head == nullptr || head->next == nullptr) {return head;}
ListNode * newHead = reverseList(head->next); head->next->next = head; head->next = nullptr; return newHead;
} };
|
性能分析
时间复杂度:O(n)。
空间复杂度:每次递归都需要将当前变量压栈,为O(n)。