链表面试题—反转链表

版权声明: https://blog.csdn.net/qq_39539470/article/details/81504664

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?(你可以迭代或递归地反转链表。你能否用两种方法解决这道题?)
方法1:从原链表的头部一个一个取节点并插入到新链表的头部
解题思路如下:
例如我们
这里写图片描述
代码:

/**
 * 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* new_head=NULL;//指向新链表的头结点指针
        while(head)
        {
            ListNode* next=head->next;//创建一个临时变量用来备份头结点的下一个指针,是为了防止下次找的时候找不到链表
            head->next=new_head;//让头结点的next指向新节点
            new_head=head;
            head=next;
        }
        return new_head;
    }
};

方法二
思路:每次都将原第一个结点之后的那个结点放在新的表头后面。
比如1,2,3,4,5
第一次:把第一个结点1后边的结点2放到新表头后面,变成2,1,3,4,5
第二次:把第一个结点1后边的结点3放到新表头后面,变成3,2,1,4,5
……
直到: 第一个结点1,后边没有结点为止。
代码如下:

class Solution {
public:
    ListNode* reverseList(ListNode* head) { 
        if(head==NULL||head->next==NULL)
            return head;
        ListNode* ans=reverseList(head->next);
        head->next=NULL;
        return ans;  
    }
};

方法三;
:对于一条链表,从第2个节点到第N个节点,依次逐节点插入到第1个节点(head节点)之后,(N-1)次这样的操作结束之后将第1个节点挪到新表的表尾即可。
变换方式:
1,2,3,4,5
1,3,2,4,5
1,4,3,2,5
5,4,3,2,1

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* p;
        ListNode* q;
        p=head->next;
        while(p->next!=NULL){
            q=p->next;
            p->next=q->next;
            q->next=head->next;
            head->next=q;
        }
        p->next=head;//成环
        head=p->next->next;
        p->next->next=NULL;
        return head;
    }

方法4: 递归
现在需要把1->2->3->4进行反转,
可以先假设2->3->4已经反转好,已经成为了4->3->2,那么接下来要做的事情就是将4->3->2看成一个整体,让这个整体的next指向1,所以问题转化了反转2->3->4。那么,
可以先假设3->4经反转好,已经成为了4->3,那么接下来要做的事情就是将4->3看成一个整体,让这个整体的next指向2,所以问题转化了反转3->4。那么,
可以先假设4(其实是4->NULL)已经反转好,已经成为了4(其实是head->4),那么接下来要做的事情就是将4(其实是head->4)看成一个整体,让这个整体的next指向3,所以问题转化了反转4。
上面这个过程就是递归的过程,这其中最麻烦的问题是,如果保留新链表的head指针呢?想到了两个办法。

struct ListNode{
    int val;
    ListNode* next;
    ListNode(int a):val(a),next(NULL){}
};

class Solution{
    ListNode* reverseLinkedList5(ListNode* head, ListNode* & new_head){ //输入参数head为旧链表的头指针。new_head为新链表的头指针。
        if(head==NULL)
            return NULL;
        if(head->next==NULL){
            new_head=head; //当处理到了旧链表的尾指针,也就是新链表的头指针时,对new_head进行赋值。因为是引用型参数,所以在接下来调用中new_head的值逐层传递下去。
            return head;
        }
        ListNode* new_tail=reverseLinkedList5(head->next,new_head);
        new_tail->next=head;
        head->next=NULL;
        return head; //输出参数head为新链表的尾指针。
    }
};

第二个办法是,增加一个引用型参数 new_head,它用来保存新链表的头指针。

struct ListNode{
    int val;
    ListNode* next;
    ListNode(int a):val(a),next(NULL){}
};

class Solution{
    ListNode* reverseLinkedList5(ListNode* head, ListNode* & new_head){ //输入参数head为旧链表的头指针。new_head为新链表的头指针。
        if(head==NULL)
            return NULL;
        if(head->next==NULL){
            new_head=head; //当处理到了旧链表的尾指针,也就是新链表的头指针时,对new_head进行赋值。因为是引用型参数,所以在接下来调用中new_head的值逐层传递下去。
            return head;
        }
        ListNode* new_tail=reverseLinkedList5(head->next,new_head);
        new_tail->next=head;
        head->next=NULL;
        return head; //输出参数head为新链表的尾指针。
    }
};

猜你喜欢

转载自blog.csdn.net/qq_39539470/article/details/81504664