Reverse Linked List
Reverse a singly linked list.
Example:
Input: 1->2->3->4->5->NULL
Output: 5->4->3->2->1->NULL
Follow up:
A linked list can be reversed either iteratively or recursively. Could you implement both?
经典的单链表逆序问题,很多公司的面试题库都会有这道题。题目让我们试着用迭代和递归两种方法使链表逆序。
solution1(迭代): 新建一个结点newHead,然后从head开始不断后移,并让head->next指向newHead,newHead变成head,head指向它后一个结点,同时移动newHead和head,重复此操作直到head为NULL,newHead为原head的末结点。
Mycode1:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* newHead = NULL;//建立新结点(逆序后的头节点)
while(head){
ListNode* temp = head->next;//保存head的下一个结点,以免断链后丢失
head->next = newHead;//逆序操作,将head断链指向newHead
newHead = head;//newHead随着head往后移
head = temp;//head变为它的下一个结点,继续遍历
}
return newHead;
}
};
solution2(迭代): 这种方法不用花费额外空间。思路是:定义一个cur结点指针,用来遍历整条链,p始终是cur指向的下一个结点。每次都让cur指向它的下下一个结点(也就是cur->next = p->next),然后把p指向head结点,同时把head对应变为p结点,这样完成一次逆序操作,同时head也变成新链表的头结点。(注意整个过程中其实cur始终是最开始的head结点没有变,但是在逆序的过程中使得cur在不断前进遍历)
Mycode2:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if (head == NULL) return NULL;
ListNode *p, *cur;
cur = head;
while(cur->next){
p = cur->next;
cur->next = p->next;
p->next = head;
head = p;
}
return head;
}
};
递归就很难写了,自己一直没写出来,好在看懂题解给出的递归的逻辑了,不禁感叹:递归果然博大精深!
solution3(递归): (按照样例给的数据讲)首先第一次进入reverseList(),newHead赋值语句会递归调用函数5次,直到函数参数变为最末结点(设为tail),tail->next=NULL,所以直接返回tail结点给上一层函数,于是回到第四层函数newHead就变为了tail,但是第四层函数的输入参数head是tail的前一个结点,于是开始逆序操作:让tail指向tail前一个结点,并置tail前一个结点的next为NULL,返回newHead。这样就通过递归完成了一次逆序(将最末两个结点逆序了),然后返回到第三层递归函数继续逆序操作,一层层返回,直到回到第一层函数,也就通过递归实现了逆序操作,返回逆序完成后的头结点newHead即可。
Mycode3:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if (!head || !head->next) return head;
ListNode* newHead = reverseList(head->next);
head->next->next = head;
head->next = NULL;
return newHead;
}
};
最后可以写一个完整的程序验证一下:
Mycode:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
struct ListNode{
int val;
ListNode* next;
ListNode(int x) : val(x), next(NULL) {}
};
ListNode* reverseList1(ListNode* head){
if (!head || !head->next) return head;
ListNode* newHead = reverseList1(head->next);
head->next->next = head;
head->next = NULL;
return newHead;
}
ListNode* reverseList2(ListNode* head) {
ListNode* newHead = NULL;//建立新结点(逆序后的头节点)
while(head){
ListNode* temp = head->next;//保存head的下一个结点,以免断链后丢失
head->next = newHead;//逆序操作,将head断链指向newHead
newHead = head;//newHead随着head往后移
head = temp;//head变为它的下一个结点,继续遍历
}
return newHead;
}
ListNode* reverseList3(ListNode* head) {
if (head == NULL) return NULL;
ListNode *p, *cur;
cur = head;
while(cur->next){
p = cur->next;
cur->next = p->next;
p->next = head;
head = p;
}
return head;
}
void Print(ListNode* head){
ListNode* p = head;
while(p){
cout << p->val << "->";
p = p->next;
}
cout << "NULL" << endl;
}
int main(){
ListNode* head = new ListNode(1);
ListNode* p = head;
ListNode* ans;
for(int i = 2; i <= 5; i++){
p->next = new ListNode(i);
p = p->next;
}
cout << "before reversed: ";
Print(head);
ans = reverseList1(head);
cout << "after reversed: ";
Print(ans);
return 0;
}
运行结果:
before reversed: 1->2->3->4->5->NULL
after reversed: 5->4->3->2->1->NULL
Hit any key to close this window...
谢谢你的观看!