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

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

203.移除链表元素

  • 讲解链接

https://programmercarl.com/0203.%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8%E5%85%83%E7%B4%A0.html

  • 看答案前

移除元素:元素所在地址从链表中移除,并且把断掉的链表链接起来。

遇到的困难:知道思路,写不出来。

  • 看答案后

原来这么简单,可为什么我写不出来?

思路:

1 定义一个虚拟头节点,该节点一开始就指向head,这样做的目的是保持处理逻辑的一致性,否则头节点的处理方法还需要另外写代码,使用的虚拟头节点就不要重写了。

2 定义一个临时节点,用于寻找要删除的元素。初始值赋为虚拟节点。

3 依次移动临时节点,发现目标元素就删除。直到移动到链表尾部。

4 删除操作:将要删除元素的后面部分链表临时存储,删除当前元素,再把存储的链表和删除前一个节点连接起来。

  • 代码
/**
 * 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) {
        ListNode* dummy_head = new ListNode(0);//生成一个虚拟头节点
        dummy_head->next = head; //将头节点和链表连起来
        ListNode* curr = dummy_head; //用于遍历链表的指针
        while(curr->next!=nullptr){
            if(curr->next->val == val){
                ListNode* temp_node = curr->next;
                curr->next = curr->next->next;
                delete temp_node;//释放内存
                temp_node = nullptr;
            }else{
                curr = curr->next;
            }
        }
        //因为存在链表头节点被删的可能,如果被删除,不做如下操作而直接返回head则链表地址会指向一个未分配内存的位置,会报错.所以需要重新赋值头节点.
        head = dummy_head->next;//
        return head;
    }
};
  • 总结

虚拟头节点是个好东西,省了好多事。

707.设计链表

讲解链接:

https://programmercarl.com/0707.%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8.html

看解答前:

我的思路:

1 实现个链表节点,很简单但是我实现的方法实在构造函数里实现的节点,这样做不可以,因为每次创建对象都回重新构造构造一个节点。

2 get实现:根据输入的索引返回对应的值。没问题。

3 addAtHead实现:知道在都节点恰插入数据,但是细节没处理好。

4 addAtTail实现:末尾添加就好,直接找到链表末尾新建一个节点链接起来。

5 addAtIndex实现:要考虑索引的大小,这里没注意细节,还是出问题了。

6 deleteAtIndex实现:删除数据后忘记对数据赋予nullptr了。

看解答后:

不得不说虚拟头节点真是好东西。真的可以节省很多事。但是链表的设计过程中index的大小还是要处理好,不然容易出错。两者配合好才行。

代码:

class MyLinkedList {
public:
    struct LInkedNode{
        int val;
        LInkedNode* next;
        LInkedNode(int val):val(val),next(nullptr){
        }
    };
    MyLinkedList():size_(0),dummy_head_(new LInkedNode(0)){
    }
    int get(int index) {
       if(index > size_ - 1||index < 0){
           return -1;
       }
       LInkedNode* curr = dummy_head_->next;
       while(index -- ){
           curr = curr->next;
       }
       int val = curr->val;
       return val;
    }
    void addAtHead(int val) {
       LInkedNode* curr = new LInkedNode(val);
       curr->next = dummy_head_->next;
       dummy_head_->next = curr;
       ++size_;
    }
    void addAtTail(int val) {
        LInkedNode* curr = dummy_head_;
        while(curr->next!=nullptr){
            curr = curr->next;
        }
        curr->next = new LInkedNode(val);
        ++size_;
    }
    void addAtIndex(int index, int val) {
        if(index >size_ )return;
        if(index < 0 )index = 0;
        LInkedNode* curr = dummy_head_;
        while(index--){
            curr = curr->next;
        }
        LInkedNode* tmp = curr->next;
        curr->next = new LInkedNode(val);
        curr->next->next = tmp;      
        ++size_;
    }
    void deleteAtIndex(int index) {
       if(index >=size_||index < 0)return;
       LInkedNode* curr = dummy_head_;
       while(index --){
           curr = curr->next;
       }
       LInkedNode* tmp = curr->next;
       curr->next = curr->next->next;
       delete tmp;
       tmp = nullptr;
       size_--;
    }
private:
int size_;
LInkedNode* dummy_head_;
};
/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList* obj = new MyLinkedList();
 * int param_1 = obj->get(index);
 * obj->addAtHead(val);
 * obj->addAtTail(val);
 * obj->addAtIndex(index,val);
 * obj->deleteAtIndex(index);
 */

总结:

脑子比手快,脑子能想到,手总是写不出来。。。

206.反转链表

讲解链接:

https://programmercarl.com/0206.%E7%BF%BB%E8%BD%AC%E9%93%BE%E8%A1%A8.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE

看解答前:

写过,用的是双指针方法,但是还是忘了,算是复习。

看解答后:

双指针已经看过,再次复习一遍,递归的写了半天还是写错。但是思路确实也比较简单。

代码:

双指针

/**
 * 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* reverseList(ListNode* head) {
        ListNode* pre = nullptr;
        ListNode* curr = head;
        while(curr!=nullptr){
        ListNode* tmp = curr->next;
        curr->next = pre;
        pre =curr;
        curr  = tmp;
        }
        return pre;
    }
};

递归

/**
 * 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* reverse(ListNode* pre,ListNode*curr){
        if(curr==nullptr)return pre;
        ListNode* tmp = curr->next;
        curr->next = pre;
        // pre = curr;
        // curr=tmp;
        return reverse(curr,tmp);
    }
    ListNode* reverseList(ListNode* head) {
        return reverse(nullptr,head);
    }
};

总结:

这些题目都是看了答案后才觉得原来如此简单,同时也注意到之前写过的算法里面用到的思路如果不及时复习,后面再次遇到时又会忘记。时间太赶,无法好好整理文章,先这样,加油。已经8.21了,洗漱出门。

相关文章
203. 移除链表元素,707.设计链表,206. 反转链表
链表是数据结构中的重要概念,包含单链表、双链表和循环链表。单链表每个节点存储数据与下一节点指针;双链表增加上一节点指针;循环链表首尾相连。 **例题解析:** 1. **203. 移除链表元素**:通过遍历链表删除指定值节点,注意处理头节点特殊情况。 2. **707. 设计链表**:实现链表的增删查操作,需理解指针操作逻辑,避免直接修改目标节点。 3. **206. 反转链表**:采用双指针或递归方法改变节点指向,完成链表反转。 以上题目涵盖链表核心操作,掌握后可灵活应对相关问题。
|
存储 算法 物联网
解析局域网内控制电脑机制:基于 Go 语言链表算法的隐秘通信技术探究
数字化办公与物联网蓬勃发展的时代背景下,局域网内计算机控制已成为提升工作效率、达成设备协同管理的重要途径。无论是企业远程办公时的设备统一调度,还是智能家居系统中多设备间的联动控制,高效的数据传输与管理机制均构成实现局域网内计算机控制功能的核心要素。本文将深入探究 Go 语言中的链表数据结构,剖析其在局域网内计算机控制过程中,如何达成数据的有序存储与高效传输,并通过完整的 Go 语言代码示例展示其应用流程。
307 0
|
存储 机器学习/深度学习 算法
C 408—《数据结构》算法题基础篇—链表(下)
408考研——《数据结构》算法题基础篇之链表(下)。
663 30
|
存储 算法 C语言
C 408—《数据结构》算法题基础篇—链表(上)
408考研——《数据结构》算法题基础篇之链表(上)。
956 25
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之单双链表精题详解(9)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
存储 Web App开发 算法
2024重生之回溯数据结构与算法系列学习之单双链表【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构之单双链表按位、值查找;[前后]插入;删除指定节点;求表长、静态链表等代码及具体思路详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
416 3
|
存储 算法 Java
Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性
Java Set因其“无重复”特性在集合框架中独树一帜。本文解析了Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性,并提供了最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的hashCode()与equals()方法。
515 4
【力扣】-- 移除链表元素
【力扣】-- 移除链表元素
269 1
|
存储 缓存 算法
经典算法之链表篇(三)
经典算法之链表篇(三)
307 4