代码随想录训练营Day3 Leetcode 203、707、206(链表基础)递归思想真有趣,设计链表多考虑。

1.Leetcode 203

题目描述:给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
思路解析:双指针法,使用虚拟头节点,避免删除头节点需要特殊判断。因为删除单链表节点需要找的目标节点的前一个节点才能进行删除,指针1从头节点的前一个即虚拟节点开始,指针2从头节点开始,指针2指向的是判断是否需要删除的节点,指针1是指针2的前一个结点。
代码演示附详细注释:
ListNode* removeElements(ListNode* head, int val) {
    //创建一个虚拟节点(head的前驱节点)
    ListNode* p = new ListNode();
    ListNode* nullHead = p;
    //并将它的next指向head
    p->next = head;

    //目标节点指针
    ListNode* target = head;
    ListNode* temp;

    //遍历链表
    while (target) {
        //存储目标节点的下一个节点
        temp = target->next;

        //处理目标节点是否需要删除

        //需要则将前驱节点p的next指向目标节点的next
        if (target->val == val) {
            p->next = temp;
        }
        //否则前驱节点向后移
        else {
            p = target;
        }

        //目标节点向后移
        target = temp;
    }

    //返回虚拟节点的下一个节点即头节点
    return nullHead->next;

}

2.Leetcode 707

题目描述:自己设计单链表并能实现以下操作
思路解析:多画图,多思考特殊情况
代码演示附详细注释:
typedef struct Node {
    int val;
    Node* next;
    Node() { val = -1; next = nullptr; }
    Node(int v) { val = v; next = nullptr; }
};
class MyLinkedList {
public:
    Node* head;
    Node* tail;
    int size;
    MyLinkedList() {
        //初始化元素个数为0
        size = 0;
        //创建一个虚拟头节点方便头插和尾插
        tail = head = new Node();
    }

    int get(int index) {
        //不存在该索引直接返回-1
        if (index < 0 || index >= size)return -1;
        Node* p = head;
        for (int i = 0; i <= index; i++) {
            p = p->next;
        }

        return p->val;
    }

    //头插法
    void addAtHead(int val) {
        Node* p = new Node(val);
        p->next = head->next;
        head->next = p;

        //特殊情况,尾指针需要指向链表的最后一个元素
        if (size == 0)tail = p;

        size++;
    }

    void addAtTail(int val) {
        Node* p = new Node(val);
        tail->next = p;
        tail = p;
        size++;
    }

    void addAtIndex(int index, int val) {
        if (index<0 || index>size)return;
        Node* p = head;
        //找要插入元素节点的前一个节点
        for (int i = 0; i < index; i++) {
            p = p->next;
        }
        Node* q = new Node(val);
        q->next = p->next;
        p->next = q;

        //当向尾端插入元素时,需要更新尾指针
        if (size == index)tail = q;
        size++;

    }

    void deleteAtIndex(int index) {
        //不存在
        if (index < 0 || index >= size)return;

        //找要删除索引节点的前一个节点
        Node* p = head;
        for (int i = 0; i < index; i++) {
            p = p->next;
        }
        Node* temp = p->next;
        p->next = temp->next;

        //当删除尾节点时,需要更新尾指针
        if (index == size - 1)tail = p;
        size--;

    }
};

3.Leetcode 206

题目描述:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
思路解析:递归版往往能体现程序设计的精髓,这里我们使用递归版,大家多思考画图。
代码演示附详细注释:
//递归函数
//第一个参数,未反转的部分链表头节点
//第二个参数,已经反转的链表头节点
ListNode* reverse(ListNode* head, ListNode* pre) {
    //没有未反转的节点了,递归出口,已经全部反转,直接返回已经反转的链表头节点
    if (!head)return pre;

    //没有到达递归出口,还有未反转的节点
    //记录下一次递归所需要反转的头节点
    ListNode* temp = head->next;

    //新的头节点指向已反转链表的节点点
    head->next = pre;

    //下一层递归
    return reverse(temp, head);

    /*举个例子  
           未反转                    已反转
    第0次:1-2-3-4-5-null            null
    第1次:2-3-4-5-null              1-null
    第2次:3-4-5-null                2-1-null
    第3次:4-5-null                  3-2-1-null
    第4次:5-null                    4-3-2-1-null
    第5次:null                      5-4-3-2-1-null
    第5次发现head为null直接return结束递归
    */

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值