力扣学习day3

链表:C/C++中单链表节点定义方式

// 单链表
struct ListNode {
    int val;  // 节点上存储的元素
    ListNode *next;  // 指向下一个节点的指针
    ListNode(int x) : val(x), next(NULL) {}  // 节点的构造函数
};

C++默认构造函数和自己定义的节点构造之间的区别: 

 

 203.移除链表元素 

题目链接:203. 移除链表元素 - 力扣(LeetCode)

讲解链接:代码随想录 (programmercarl.com) 

1)不使用虚拟头节点

对头节点和非头节点分开讨论。如果是要移除头节点时,将head指向head的下一个节点即可;如果是非头节点时,待移除节点的上一个节点的指针指向待移除节点的下一个节点即可。

    class Solution {
    public:
        ListNode* removeElements(ListNode* head, int val) {
            //直接用原来的链表进行操作;对头节点和非头节点分类讨论
            while (head != NULL && head->val == val)//当头节点是目标元素时
            {
                ListNode* cmp = head;//cmp储存待删去元素
                head = head->next;
                delete cmp;//记得释放空间
            }

            ListNode* cur = head;/*开始删除非节点元素,cur指向检测元素的上一个节点,因为删一个节点时,需要该节点的上一个节点的指针指向其下一个节点的数据,而单向的节点无法回溯上一个节点*/
            while (cur != NULL && cur->next != NULL)//cur节点和当前节点都不为空时
            {
                if (cur->next->val == val)//进行判断cur的下一个节点的值是否满足要求
                {
                    ListNode* cmp = cur->next;
                    cur->next = cur->next->next;
                    delete cmp;
                }
                else
                {
                    cur = cur->next;//进行下一个元素的检测
                }
            }
            return head;
        }
};

 PS:C++记得移除元素后释放空间

2)虚拟头节点法

即在头节点前方创立一个新节点,新节点的指针指向头节点,这样头节点和非头节点的处理方式就一致了。

    class Solution {
    public:
        ListNode* removeElements(ListNode* head, int val) {
            //虚拟头节点法
            ListNode* dummyHead = new ListNode(0);//创建一个虚拟节点,指向head
            dummyHead->next = head;
            ListNode* cur = dummyHead;/*开始删除非节点元素,cur指向检测元素的上一个节点,因为删一个节点时,需要该节点的上一个节点的指针指向其下一个节点的数据,而单向的节点无法回溯上一个节点*/
            while (cur != NULL && cur->next != NULL)//cur节点和当前节点都不为空时
            {
                if (cur->next->val == val)//进行判断cur的下一个节点的值是否满足要求
                {
                    ListNode* cmp = cur->next;
                    cur->next = cur->next->next;
                    delete cmp;
                }
                else
                {
                    cur = cur->next;//进行下一个元素的检测
                }
            }
            return dummyHead->next;
        }
    };

707.设计链表

题目链接: 707. 设计链表 - 力扣(LeetCode)

讲解链接:代码随想录 (programmercarl.com) 

参考代码:

 

class MyLinkedList {
public:
    //定义链表结构体
    struct LinkedNode {
        int val;
        LinkedNode* next;
        LinkedNode(int val) :val(val), next(nullptr) {}
    };
    MyLinkedList() {
        dummyHead = new LinkedNode(0);
        _size = 0;
    }

    int get(int index) {
        //首先判断index是否合法,当index<0或者index>_size-1时非法
        LinkedNode* cur = dummyHead->next;
        if (index > (_size - 1) || index < 0)
        {
            return -1;
        }
        while (index--)
        {
            cur = cur->next;
        }
        return cur->val;
    }

    void addAtHead(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        newNode->next = dummyHead->next;
        dummyHead->next = newNode;
        _size++;
    }

    void addAtTail(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = dummyHead;
        while (cur->next != NULL)
        {
            cur = cur->next;//找到最优一个元素的位置
        }
        cur->next = newNode;
        _size++;
    }

    void addAtIndex(int index, int val) {
        //首先判断n的合法性
        if (index < 0)index = 0;//在头部插入节点
        if (index > _size)return;//大于链表长度,不插入
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = dummyHead;
        while (index--)
        {
            cur = cur->next;
            //cur->next指向第index个元素
        }
        newNode->next = cur->next;
        cur->next = newNode;
        _size++;
    }

    void deleteAtIndex(int index) {
        LinkedNode* cur = dummyHead;
        if (index<0 || index>_size - 1)
        {
            return;
        }
        else
        {
            while (index--)
            {
                cur = cur->next;
            }
            LinkedNode* cmp = cur->next;
            cur->next = cur->next->next;
            delete cmp;//释放空间
            _size--;
        }
    }
private:
    int _size;//数组大小
    LinkedNode* dummyHead;//虚拟头节点

};

206.反转链表

题目链接:206. 反转链表 - 力扣(LeetCode) 

讲解链接:代码随想录 (programmercarl.com) 

1)双指针法

首先定义两个指针,指针pre初始化为NULL,因为第一个元素反转后变成最后一个元素所指向的即为NULL,指针cur初始化为head,即从head开始反转。当cur为NULL时,停止反转,返回pre即可。

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* cur = head;
        ListNode* pre = NULL;//初始化,第一个值翻转过来后指向NULL
        while (cur)
        {
            ListNode* temp = cur->next;//用一个临时节点储存下一个值
            cur->next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }
};

 2)递归法

逻辑同双指针法,只是更加简洁

class Solution {
public:
    ListNode* reverse(ListNode* pre, ListNode* cur)
    {
        if (cur == NULL) return pre;//递归结束
        ListNode* temp;
        temp = cur->next;
        cur->next = pre;//翻转
        return reverse(cur, temp);//现在的cur是下一个pre,现在的temp是下一个cur
    }
    ListNode* reverseList(ListNode* head) {
        return reverse(NULL, head);//初始值同双指针法
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值