终于学会链表反转了【算法通关村第二关】

今天是链表反转的2个常用方法。
反转要求如下:
对应力扣206题。
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
终于学会链表反转了【算法通关村第二关】_第1张图片
输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1]

【方法一】虚拟头结点

处理流程图
终于学会链表反转了【算法通关村第二关】_第2张图片

  • 首先创建虚拟节点,然后再创建一个指针cur指向当前头结点。
  • 从头结点开始循环,当前节点cur->next连接转向虚拟节点的下一个节点。
    • 因为在整个过程中虚拟节点永远是头结点前面一个节点,next值一直指向头结点。
  • 这时候虚拟节点的next值又需要指向接到头结点上的新的头结点。

java代码:

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode ans = new ListNode(-1); //创建的虚拟节点
        ListNode cur = head; //保留当前头结点使用,防止修改原链表。
        while(cur != null) {  //循环直到完毕
            ListNode next = cur.next;  //保存下一个节点,用于下一次循环。
            cur.next = ans.next; //原头结点下一个节点修改为虚拟节点的下一个
            ans.next = cur; //虚拟节点连接到最新头结点
            cur = next;  //跳到下一个节点
        }
        return ans.next; 
    }
}

C++代码:

ListNode* reverseList(ListNode* head) {
        ListNode * vir = (struct ListNode *)malloc(sizeof(struct ListNode));
        vir->next = NULL;  
        ListNode * cur = head;
        while(cur != NULL) {
            ListNode * next = cur->next;
            cur->next = vir->next;
            vir->next = cur;
            cur = next;
        }
        return vir->next;
        
    }

【方法二】双指针

一前一后两个快慢指针,最后返回pre就是反转后的链表。具体看动画即可明白。

C++:

ListNode* reverseList(ListNode* head) {
    //先创建两个指针,一个指向头,一个指向头结点前一个节点null
        ListNode * cur = head;
        ListNode * pre = NULL;
        while(cur) {
            ListNode * temp = cur->next;  //用于循环。
            cur->next = pre;  //链表反转过来即可
            //接下来两个指针都往后走一个单位,进行下一次循环。
            pre = cur;
            cur = temp;
        }
        return pre;
    }

java:

ublic ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;
        while(cur != null) {
            ListNode temp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }

【方法三】递归方法

递归方法还是没有搞明白

// 边缘条件判断
        if(head == NULL) return NULL;
        if (head->next == NULL) return head;
        
        // 递归调用,翻转第二个节点开始往后的链表
        ListNode *last = reverseList(head->next);
        // 翻转头节点与第二个节点的指向
        head->next->next = head;
        // 此时的 head 节点为尾节点,next 需要指向 NULL
        head->next = NULL;
        return last;

但是根据双指针法衍生出的递归方法本质上还是不难的。

ListNode* reverse(ListNode* pre,ListNode* cur){
        if(cur == NULL) return pre;
        ListNode* temp = cur->next;
        cur->next = pre;
        // 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步
        // pre = cur;
        // cur = temp;
        return reverse(cur,temp);
    }
    ListNode* reverseList(ListNode* head) {
        // 和双指针法初始化是一样的逻辑
        // ListNode* cur = head;
        // ListNode* pre = NULL;
        return reverse(NULL, head);
    }

你可能感兴趣的:(算法通关村第一期,算法,链表,算法,数据结构)