Reverse Linked List

6 篇文章 0 订阅
5 篇文章 6 订阅

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...

谢谢你的观看!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值