• LeetCode :206.反转链表


    题目

    反转一个单链表。

    示例

    输入:

    1->2->3->4->5->NULL
    

    输出:

    5->4->3->2->1->NULL
    

    解法探析

    解法 1:迭代法

    思路分析

    在遍历链表时,将当前结点的 next 指针改为指向其前一个结点。由于结点不会指向前一个结点,因此必须先存储其前一个结点。在更改指向之前,还需要另外一个指针来存储后一个结点。最后,返回新的头指针。

    代码实现

    C实现:

    struct ListNode {
        int val;
        struct ListNode* next;
    };
    
    struct ListNode* reverseList(struct ListNode* head)
    {
        struct ListNode* node = head;               // 当前指针,指向当前遍历到的结点
        struct ListNode* prev = NULL;               // 前驱指针,指向当前结点的前一个结点
        struct ListNode* reverseHead = NULL;        // 新的头指针,指向反转后链表的头结点,即原始链表的尾结点
    
        // 若当前指针不为 NULL
        while (node != NULL) {
            struct ListNode* pNext = node->next;    // 后继指针,指向当前结点的后一个结点
    
            if (pNext == NULL) {                    // 若后继指针为 NULL,则已到链表的末尾,新的头指针等于当前指针
                reverseHead = node;
            }
    
            node->next = prev;                      // 当前结点的 next 指针指向前驱结点
            
            prev = node;                            // 更新前驱指针
            node = pNext;                           // 当前指针后移
        }
    
        return reverseHead;
    }
    

    C++实现:

    struct ListNode {
          int val;
          ListNode* next;
          ListNode(int x) : val(x), next(nullptr) {}
    };
    
    class Solution {
    public:
        ListNode* reverseList(ListNode* head) {
            ListNode* node = head;
            ListNode* prev = nullptr;
            ListNode* reverseHead = nullptr;
    
            while (node != nullptr) {
                ListNode* pNext = node->next;
    
                if (pNext == nullptr) {
                    reverseHead = node;
                }
    
                node->next = prev;
    
                prev = node;
                node = pNext;
            }
            return reverseHead;
        }
    };
    

    GO实现:

    type ListNode struct {
        Val int
        Next *ListNode
    }
    
    func reverseList(head *ListNode) *ListNode {
        node := head
        var prev *ListNode = nil
        var reverseHead *ListNode = nil
        
        for node != nil {
    
            pNext := node.Next
    
            if pNext == nil {
                reverseHead = node
            }
    
            node.Next = prev
    
            prev = node
            node = pNext
        }
    
        return reverseHead
    }
    

    复杂度分析

    时间复杂度:(O(n))(假设 n 为链表的长度)
    空间复杂度:(O(1))

    动态图解

    解法 2:递归法

    思路分析

    递归法稍微复杂了一些,其关键在于反向工作。假设链表是 1->2->3->4->5->NULL,则递归过程如下:

    1.底层最后一个 reverseList(5) 返回了 5 这个结点。
    2.在 reverseList(4) 中,reverseHead 为 5,head 为4,head->next->next = head 相当于 5->4。
    3.此时结点的情况为 4->5->4,为了防止链表循环,使用 head->next = null 切断 4->5 这一条,最后返回:5->4->NULL。
    4.返回到上一层 reverseList(3),最后返回:5->4->3->NULL。
    5.reverseList(2)、reverseList(1) 依次类推,最后返回:5->4->3->2->1->NULL。

    代码实现

    C实现:

    // 定义单链表的结点类型
    struct ListNode {
        int val;
        struct ListNode* next;
    };
    
    struct ListNode* reverseList(struct ListNode* head)
    {
        // 若当前结点为 NULL,或者下一个结点为 NULL,则递归终止
        if (head == NULL || head->next == NULL) {
            return head;
        }
    
        // 结点 reverseHead 就是反转链表的头结点 
        struct ListNode* reverseHead = reverseList(head->next);
    
        // 将反转链表的尾结点(head->next)的 next 指向当前即将反转的结点
        // 如果链表是 1->2->3->4->5,那么此时的 reverseHead 就是5,
        // 而 head 是4,head 的下一个是5,下下一个是空,所以 head->next->next 就是5->4
        head->next->next = head;
    
        // 防止链表循环,将head->next置为 NULL
        head->next = NULL;
    
        // 每层递归函数都返回reverseHead,也就是最后一个结点
        return reverseHead;
    }
    

    C++实现:

    struct ListNode {
          int val;
          ListNode* next;
          ListNode(int x) : val(x), next(nullptr) {}
    };
    
    class Solution {
    public:
        ListNode* reverseList(ListNode* head) {
            if (head == nullptr || head->next == nullptr) {
                return head;
            }
    
            ListNode* reverseHead = reverseList(head->next);
            head->next->next = head;
            head->next = NULL;
            return reverseHead;
        }
    };
    

    GO实现:

    type ListNode struct {
        Val int
        Next *ListNode
    }
    
    func reverseList(head *ListNode) *ListNode {
        if head == nil || head.Next == nil {
            return head
        }
    
        reverseHead := reverseList(head.Next)
    
        head.Next.Next = head
        head.Next = nil
    
        return reverseHead
    }
    

    复杂度分析

    时间复杂度:(O(n))(假设 n 为链表的长度)
    空间复杂度:(O(n))(由于使用递归,会使用隐式栈空间,递归深度可能会达到 n 层)


    个人主页:

    www.codeapes.cn

  • 相关阅读:
    Redis持久化
    Redis配置文件详解
    Linux
    有图有真相
    Redis五大数据类型
    Redis基本知识
    Mysql主从复制
    Python脚本实现KVM虚机添加磁盘
    JQuery制作环形进度条
    JQuery制作标签
  • 原文地址:https://www.cnblogs.com/codeapes666/p/12264320.html
Copyright © 2020-2023  润新知