【C++编程能力提升—Day3】

C++编程能力提升 Leetcode—01背包 阅读详情

一、203 移除链表元素

题目链接:203 移除链表元素

核心:使用虚拟节点dummyHead,即head前增加一个val=0的节点,目的是从第一个节点开始查找元素;要求移除某元素,意味着需要遍历到该移除元素的前一个节点(cur),而不是当下要移除的节点(cur->next),移除时令前一个节点指向该移除节点的下一个节点,移除之后需delete该节点。
方法:初始化时令cur指向dummyHead,遍历链表节点时从cur->next开始,就能从第一个节点开始遍历。
若不使用虚拟节点dummyHead,此时遍历时实际是从第二个节点开始,即跳过了第一个节点,因此需要在循环结束后单独对第一个节点判断;而且也需要在程序最开始处判断当前链表是否为空。

    ListNode* removeElements(ListNode* head, int val) {
    //使用虚拟头节点dummyHead,位于当前head前一个,目的是能遍历所有元素
    ListNode* dummyHead=new ListNode(0);    //注意如何初始化
    dummyHead->next=head;   
    ListNode* cur=dummyHead;    //由cur->next遍历该链表
    while(cur->next)
    {//实际从第一个节点开始遍历,无需对第一个节点特殊处理
        if(cur->next->val==val)
        {
            ListNode* temp=cur->next;
            cur->next=temp->next;
            delete temp;
        }
        else 
            cur=cur->next;
    }
    return dummyHead->next; //返回的是虚拟节点的下一个,而不再是head!

    /*
    //未使用虚拟头节点
    if(head==NULL)
        return head;
    ListNode* cur=head;//记录原链表的头结点
    while(cur->next)
    {//实际从第二个节点开始遍历
        if(cur->next->val==val)
        {
            ListNode* temp=cur->next;   //记录待删除的节点
            cur->next=temp->next;       //当前节点的下一个节点跳过待删除节点
            delete temp;                //必须删除该节点
        }
        else 
            cur=cur->next;      
    }
    if(head->val==val)
    {//判断第一个head节点是否为val
        ListNode* temp=head;
        head=head->next;
        delete temp;   
    }
    return head;
    */
    }

二、707 设计链表

题目链接:707 设计链表

核心:
第一,定义链表节点的结构体;
第二,引入虚拟节点,方便插入函数、查找函数、删除函数的实现;
第三,熟悉类的编写,成员变量应在private里,public里的成员函数无需定义成员变量。
第四,删除函数在删除某节点后,先使用delete释放该节点的内存,再令该节点赋值为nullptr,因为释放内存后该节点是一个野指针,可能为任意值。

class MyLinkedList {
public:
    //定义链表节点结构体
    struct LinkedNode {
        int val;
        LinkedNode* next;
        LinkedNode(int val):val(val),next(nullptr) {}   //构造函数
    };
    //引入虚拟节点
    //初始化链表
    MyLinkedList() {
        dummyHead=new LinkedNode(0);    //记住:dummyHead的类型不在此定义!
        size=0;     //size的类型也不在此定义,都在private里单独定义
    }
    //获取下标为index的节点元素
    int get(int index) {
        if(index<0 || index>=size)
            return -1;
        LinkedNode* cur=dummyHead->next;
        while(index--)
        {//直到index==0时cur指向元素即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;//注意此时cur初始化为虚拟节点,而不再是第一个节点
        while(cur->next)
        {//由于退出循环时要求cur必须指向最后一个节点,而不是nullptr
            cur=cur->next;
        }
        cur->next=newNode;
        size++;
    }
    
    void addAtIndex(int index, int val) {
        if(index>size) 
            return;//index大于长度则return,表示不会插入节点
        if(index<0)
            index=0;   //特殊情况特殊处理
        LinkedNode* newNode=new LinkedNode(val);
        LinkedNode* cur=dummyHead; //必须初始化为虚拟节点
        while(index--)
        {//退出循环时要求cur指向待插入节点的前一个,否则无法插入新节点
            cur=cur->next;
        }
        newNode->next=cur->next;
        cur->next=newNode;
        size++;
    }
    
    void deleteAtIndex(int index) {
        if(index<0 || index>=size)
            return;
        LinkedNode* cur=dummyHead;
        while(index--)
        {//退出循环时要求cur指向index前一个节点
            cur=cur->next;
        }
        LinkedNode* temp=cur->next;
        cur->next=temp->next;
        delete temp;
        temp=nullptr;   //注意:需令释放内存后的temp赋值为空
        size--;
    }
private:
    LinkedNode* dummyHead;  
    int size;
};

/**
 * 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 反转链表

题目链接:206 反转链表

核心:反转链表实质是改变各节点的next指向,具体而言,原链表第一个节点反转后应指向nullptr,第二个节点指向第一个节点,以此类推,最后一个节点指向倒数第二个节点,反转后的头结点head即原链表的最后一个节点。
第一,cur指向原链表的head,目的是遍历各节点,直到最后一个节点;
第二,pre初始化指向nullptr,实质是与cur实现反转,即cur->next=pre;
第三,完成一次反转需立即更新pre和cur,先pre后cur,因为pre是更新到此时cur所在节点,而cur是更新到反转前的下一个节点,最后一次更新后,cur指向nullptr,pre指向原链表的最后一个节点,即反转后链表的头结点。

1、方法1:双指针法

令pre和cur分别为两个双指针,cur遍历当前链表元素,直至最后一个元素结束遍历;pre为反转前cur的前一个元素,即在pre和cur之间实现两个节点的反转;一次反转之后需更新pre和cur指针,均向前移一个节点,即pre=cur,cur=cur->next。

    ListNode* reverseList(ListNode* head) {
        ListNode* cur=head;
        ListNode* pre=nullptr;  //记录反转后cur的下一个节点
        ListNode* temp; //记录反转前cur的下一个节点
        while(cur)
        {//cur从head遍历链表各节点
            temp=cur->next; 
            cur->next=pre;  //reverse
            //更新cur和pre,必须先更新pre后cur 
            pre=cur;    //最后一次更新后pre指向反转前链表的最后一个节点
            cur=temp;   //最后一次更新后cur指向nullptr,          
        }
        return pre;
    }

2、递归法

实质与双指针相同,首先需构造一个实现两节点反转的函数,即传入参数是双指针pre和cur;
(1)基底条件是cur遍历完链表所有元素,即cur为空时返回此时cur的前一个节点pre;
(2)递归条件是cur非空时(cur指向节点有效),需与前一个节点pre完成反转,反转之后进入下一次递归,传入参数需更新,即pre=cur,cur=cur->next。

    ListNode* reverse(ListNode* pre, ListNode* cur)
    {//构造一个节点反转的函数,传入的参数即双指针法的pre和cur
        if(!cur)
            return pre; //base case
        ListNode* temp=cur->next; //recursion case 
        cur->next=pre;  //reverse
        return reverse(cur,temp);
    }

	ListNode* reverseList(ListNode* head) {
        //递归法,实质与双指针相同
        ListNode* cur=head;
        ListNode* pre=nullptr;
        return reverse(pre,cur);
    }
绑定压力的计算方法 压强的公式为P=F/S,其中P为ACF要求的本压压强范围,S为受压面积,F为本压压头施加的力。绑定参数需要按线体按压头进行DOE确认,并使用DOE确认好的参数按压头重新绑定标识好送ACF厂商实测固化率、粒子变形的情况,避免绑定参数导致的异常,在绑定参数的设定过程中温度和时间可以使用仪器实测但绑定的压力则需要换算。工程上绑定压力换算的原则是:1、FPC属于柔性物料,柔性物料的受压面积按FPC绑定的受压面积=FPC绑定的长度。一、工程上FOG FPC本压压力换算(柔性材料以挤压的接触面积=受力面积)F=P。 阅读详情

相关推荐

新手友好!C#上位机调用YOLO实现设备异常检测(详细步骤,附踩坑指南)

C#上位机调用YOLO实现设备异常检测,核心是把“工控交互”和“AI检测”的优势结合起来,新手不用追求一步到位,先跑通基础流程,再逐步优化性能和功能。我当初也是从踩坑中过来的,只要把核心链路和细节摸透,其实门槛并没有想象中高。如果你们在实操中遇到了具体问题(比如相机取流卡顿、模型推理报错),可以在评论区留言,后续我也可以针对性拆解具体模块的完整代码。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 628

桌面端编程之通过C++的标准模板库代码快速提高编程能力

本文描述了通过C++的标准模板库代码快速提高编程能力的方法,帮助读者写出标准规范、质量高的代码。

audyxiao001的博客 636

每日一题,快乐LeetCode C++编程之旅

本文还有配套的精品资源,点击获取 简介:LeetCode作为在线编程平台,提供大量算法题,帮助程序员提升编程和解决问题能力。“Happy-Leetcode-Per-Day”项目以C++语言为主,通过每日解决一道题,记录解题思路,旨在创造持久快乐的学习体验。C++因其性能优化、面向对象、模板编程和丰富的STL等特性,成为编程竞赛和工程实践中的优选语言。该项目不仅增强个人编程技...

weixin_32252929的博客 1675

C++ Practical-1 day2

/ 定义一个结构体,用于表示点int x;int y;// 创建一个点Point p;p.x = 10;p.y = 20;// 输出点的坐标// 创建另一个点// 列表初始化// 修改并输出点的坐标return 0;C++11允许在结构体中定义函数,这使得结构体可以包含方法。#include // 用于sqrt函数// 定义一个结构体,用于表示点,并包含一个方法int x, y;// 方法:计算点到原点的距离return 0;

wesigj的博客 1431

视频教程-《信息学竞赛-C/C++入门》 C++语言-C/C++

《信息学竞赛-C/C++入门》 C++语言 毕业于清华大学,曾担任Googl...

weixin_27035465的博客 1837

C++编程语言学习与实践:牛连强教授习题解析集

C++是一种静态类型、编译式、通用的编程语言,它支持过程化编程、面向对象编程以及泛型编程C++以其高效率和灵活性闻名,广泛应用于系统软件、游戏开发、嵌入式系统等领域。类是C++中用于创建自定义数据类型的蓝图或模板。一个类定义了一组属性(数据成员)和操作(成员函数)。创建一个对象就是将类的蓝图实例化为具体的实体。在C++中定义一个类,需要使用关键字class或struct,成员函数可以在类的内部定义,也可以在外部定义,而数据成员则通常定义在类的内部。

weixin_31176789的博客 843

从CVI(C)到Pyside(python)/Qt(C++)/VS(C#)的一点吐槽

Tkinter 布局助手”,是我接触过的基于python原生的图形界面套件Tkinter来做GUI程序的最佳实践,链接是https://www.pytk.net/],在web上就可以拖拽基础控件到面板,并定义控件的回调函数,完了存盘到本机。我曾经死抱着CVI不放,没有去追逐更现代的IDE,究其原因,主要是以前没有 AI 辅助编程,很多新 IDE 摸都不敢摸,随便一个编译报错或环境配错,就会卡死我半天。所以,遇到我这样,时不时输出一个学习心得的老工程师,也应该算是一种缘分了,很罕见的哦。

qq_15084199的博客 226

ESPON 700FW清零软件,废墨收集垫寿命错误清零,废油墨垫计数器重置10000次

ESPON 700FW清零软件,废墨收集垫寿命错误清零,重置10000次使用方法参阅,亲测https://jiuai.blog.csdn.net/article/details/122802196

上一篇: 【C++编程能力提升】
下一篇: C++编程能力提升--Day4
hyljoyhyl
博客等级 码龄9年 7粉丝 · 55原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值