代码随想录算法训练营第三天| 203.移除链表元素,707.设计链表,206.反转链表。

代码随想录算法训练营第三天| 203.移除链表元素,707.设计链表,206.反转链表。

203.移除链表元素

题目链接:203. 移除链表元素,难度:简单
在这里插入图片描述
【实现代码】

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        while (head != nullptr && head->val == val) {
            ListNode* tmp = head;
                head = head->next;
                delete tmp;
        }
        ListNode *curNode = head;
        while (curNode != nullptr && curNode->next != nullptr) {
            if (curNode->next->val == val) {
                ListNode *tmpNode = curNode->next;
                curNode->next = curNode->next->next;
                delete tmpNode;                            
            } else {
                curNode = curNode->next;
            }            
        }
        return head;
    }
};

【解题思路】

  1. 首先判断头节点是否是val,若是单独对头节点处理
  2. 头节点不是val时,判断当前节点的下一个节点是否不为空且其->val是否等于val
  3. 若是,则将当前节点指向下下一个节点,并将当前节点的下一个节点删除>

【总结】

【第一想法】在脑中已经有了链表删除的图片,觉得问题不大吧
【存在的问题】只记得原理,对结构体的指针理解不到位,不能直接实现
【收获】理解了结构体指针的用法

707. 设计链表

题目链接:707. 设计链表,难度:中等
在这里插入图片描述
【实现代码】

class MyLinkedList {
public:
    struct LinkedNode {
        int val;
        LinkedNode* next;
        LinkedNode(int val) : val(val), next(nullptr){} 
    };

    MyLinkedList() {
        this->_size = 0;
        this->_dummyHead = new LinkedNode(0);
    }
    
    int get(int index) {
        if (index >= this->_size || index < 0) {
            return -1;
        }
        LinkedNode* cur = this->_dummyHead->next;
        for (int i = 0; i < index; i++) {
            cur = cur->next;
        }
        return cur->val;
    }
    
    void addAtHead(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        if (this->_dummyHead != nullptr) {
            newNode->next = this->_dummyHead->next;
            this->_dummyHead->next = newNode;
            this->_size++;
        }        
    }
    
    void addAtTail(int val) {        
        if (this->_dummyHead != nullptr) {
            LinkedNode* newNode = new LinkedNode(val);
            LinkedNode* cur = this->_dummyHead;
            while (cur->next != nullptr) {
                cur = cur->next;
            }
            cur->next = newNode;
            this->_size++;
        }        
    }
    
    void addAtIndex(int index, int val) {
        if (index < 0) {
            index = 0;
        } else if (index > this->_size) {
            return ;
        }
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = this->_dummyHead;
        for (int i = 0; i < index; i++) {
            cur = cur->next;
        }
        newNode->next = cur->next;
        cur->next = newNode;
        this->_size++;
    }
    
    void deleteAtIndex(int index) {
        if (index >=0 && index < this->_size) {
            LinkedNode* cur = this->_dummyHead;
            for (int i = 0; i < index; i++) {
                cur = cur->next;
            }
            LinkedNode* tmp = cur->next;
            cur->next = cur->next->next;
            delete tmp;
            this->_size--;
        }
    }

private:
    int _size;
    LinkedNode* _dummyHead;
};

【总结】

【第一想法】有了第一题的链表练习之后,基本掌握了链表的操作,觉得难度不大。
【存在的问题】

  1. 对于类的成员不太清楚需要创建什么,也不知道还要创建一个结构体;
  2. 写的程序也基本通过了验证,比较示例代码后,发现自己写的很多有冗余,判断条件太细,造成了冗余。
  3. 力扣给的示例有点小问题,声明类对象使用了new,需要用指向对象的指针接收,或者不用new。

【收获】掌握了链表的各种操作。

206. 反转链表

题目链接:206. 反转链表,难度:简单
在这里插入图片描述
【实现代码】

//双指针实现
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* preNode = nullptr;
        ListNode* curNode = head;
        ListNode* nextNode;
        while (curNode != nullptr) {
            nextNode = curNode->next;
            curNode->next = preNode;
            preNode = curNode;
            curNode = nextNode;            
        }
        head = preNode;
        return head;
    }
};
//递归实现1
class Solution {
public:
    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);
    }

};
//递归实现2
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        // 边缘条件判断
        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;
    }
}; 

【解题思路】

和数组的反转相似,不同的是,链表的反转需要额外的空间(链表的指针空间)存储前一个节点和下一个节点。

【总结】

【存在的问题】在未看讲解时,分析的太复杂且不清楚。
【收获】加深了对链表指针的掌握

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值