代码随想录算法训练营第三天 |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了,洗漱出门。

相关文章
|
5天前
|
程序员
【刷题记录】移除链表元素
【刷题记录】移除链表元素
|
2天前
|
机器学习/深度学习 人工智能 自然语言处理
【自然语言处理】TF-IDF算法在人工智能方面的应用,附带代码
TF-IDF算法在人工智能领域,特别是自然语言处理(NLP)和信息检索中,被广泛用于特征提取和文本表示。以下是一个使用Python的scikit-learn库实现TF-IDF算法的简单示例,并展示如何将其应用于文本数据。
115 65
|
3天前
|
存储 算法
LeetCode第83题删除排序链表中的重复元素
文章介绍了LeetCode第83题"删除排序链表中的重复元素"的解法,使用双指针技术在原链表上原地删除重复元素,提供了一种时间和空间效率都较高的解决方案。
LeetCode第83题删除排序链表中的重复元素
|
2天前
|
机器学习/深度学习 人工智能 算法
【人工智能】传统语音识别算法概述,应用场景,项目实践及案例分析,附带代码示例
传统语音识别算法是将语音信号转化为文本形式的技术,它主要基于模式识别理论和数学统计学方法。以下是传统语音识别算法的基本概述
9 2
|
5天前
|
存储 C语言
【数据结构】c语言链表的创建插入、删除、查询、元素翻倍
【数据结构】c语言链表的创建插入、删除、查询、元素翻倍
【数据结构】c语言链表的创建插入、删除、查询、元素翻倍
|
6天前
|
搜索推荐 算法 Java
|
6天前
|
搜索推荐 算法 Java
插入排序算法(Java代码实现)
这篇文章通过Java代码示例详细解释了插入排序算法的实现过程,包括算法的基本思想、核心代码、辅助函数以及测试结果,展示了如何通过插入排序对数组进行升序排列。
|
2月前
|
存储 SQL 算法
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
|
2月前
|
存储 SQL 算法
LeetCode 题目 86:分隔链表
LeetCode 题目 86:分隔链表
|
2月前
|
存储 算法 Java
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
17 2