代码随想录——翻转链表

题目

解法一(比较烂的双指针)

206. 反转链表

自己愚钝,想不清楚如何简化代码结构,没有领悟双指针的精髓

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* reverseList(struct ListNode* head){
    if (head == NULL || head->next == NULL) return head;  // 如果链表为空或只有一个结点,直接返回结点即可

    struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
    cur = head->next;
    head->next = NULL;

    while (cur != NULL) {
        if (cur->next == NULL) {  // 确保最后一个结点完成翻转
            cur->next = head;
            break;
        }
        struct ListNode* tmp = (struct ListNode*)malloc(sizeof(struct ListNode));
        tmp = cur->next;
        // printf("head = %d cur = %d tmp = %d\n", head->val, cur->val, tmp->val);
        cur->next = head;
        head = cur;
        cur = tmp;
    }
    return cur;
}

解法二(优化的双指针)

struct ListNode* reverseList(struct ListNode* head){
    struct ListNode* cur = (struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode* pre = (struct ListNode*)malloc(sizeof(struct ListNode));

    cur = head; // 保存当前结点
    pre = NULL; // 保存上一个结点

    while (cur != NULL) {
        head = head->next;  // 记录下一个结点
        cur->next = pre;
        pre = cur;
        cur = head;
    }

    return pre; // 当跳出循环时,pre指向最后一个结点
}

解法三(递归)

对我来说有点绕,我捋了半天

struct ListNode* reverseList(struct ListNode* head){
    // 函数边界条件
    if (head == NULL) return NULL; // 链表为空的情况
    if (head->next == NULL) return head; // 链表只有一个结点的情况

    struct ListNode* last = (struct ListNode*)malloc(sizeof(struct ListNode));
    last = reverseList(head->next); // 一直递归到链表的最后一个节点,相当于计数链表的长度,然后从头开始逐个节点翻转
    // 从链表头开始,逐个翻转节点指向,当前的head是
    head->next->next = head; // 将下一个节点指向当前节点,即翻转
    head->next = NULL;  // 将当前节点反转后是两个节点组成的链的尾部,所以指向NULL
                        //下一轮递归该节点将与前一个结点作为一个短链翻转,会被修改指向前一个结点

    return last; // 一直返回原链表的最后一个结点,即新链表头节点
}
posted @ 2022-09-09 09:32  番茄元  阅读(27)  评论(0)    收藏  举报