Leetcode部分经典链表题解析(涉及链表的反转、排序、合并、移除元素、成环、相交等操作)

2023-05-16

链表相关问题

第206题 反转链表

要求:将给定链表进行反转操作,第一个结点作为尾结点,第二个结点指向第一个节点,以此类推,使得原链表的尾结点作为答案的头结点。

思路一:逐步操作

1)设置结点prev(初始化为null)
2)从头结点开始,记录当前结点(cur)的下一个结点(next),将cur指向prev后,prev前移一个(对于新链而言前移),cur后移一个到被记录的next上(对于原链而言后移)
3)当cur在原链表上已被后移到null时,结束循环
这种方法更加重要。

    //反转链表
    ListNode* reverseList1(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* cur = head;
        while (cur) {
            ListNode* next = cur->next;
            cur->next = prev;
            prev = cur;
            cur = next;
        }
        return prev;
    }

思路二:巧用栈

1)定义一个stack
2)从头结点开始依次入栈,直至链尾
3)栈内结点依次出栈,让新链表的链尾每次都指向栈顶结点,直至栈空

    ListNode* reverseList2(ListNode* head) {
        stack<ListNode*> s1;
        ListNode* cur1 = head;
        //入栈操作
        while (cur1) {
            s1.push(cur1);
            cur1 = cur1->next;
        }
        ListNode* tmp = new ListNode(0);
        ListNode* ans = tmp;
        //出栈操作
        while (!s1.empty()) {
            tmp->next = s1.top();
            tmp = tmp->next;
            s1.pop();
        }
        tmp->next = nullptr;
        return ans->next;
    }

第61题 旋转链表

要求:给定一个链表的头节点head,旋转链表,将链表每个节点向右移动 k 个位置,每移动一次,都让当前链表的尾结点指向头结点,倒数第二个结点成为尾结点。

分析过程:
1)若链表一共有m个结点,旋转一次后,第m个结点成为头结点;旋转两次后,第m-1个结点成为头结点,旋转k(k≤m-1)次后,m-k+1个结点成为头结点。旋转m次后,原链表头结点将再次成为头结点。
2)旋转链表是一个循环操作,即对于所有的k(k除以m的余数相同),旋转k次,得到的链表头结点相同

解题思路

1)找到链表的节点个数(count)
2)取k除以count的余数,即为缩小的旋转次数
3)头结点为第count-k+1个,使用for循环找到该结点
4)改变相应结点的next指针,得到新链表

    //旋转链表
    ListNode* rotateRight(ListNode* head, int k) {
        if (!head) return nullptr;
        ListNode* tmp1 = head;
        int count = 1;
        //找到链表的节点个数(count)
        while (tmp1->next != nullptr) {
            tmp1 = tmp1->next;
            count++;
        }
        tmp1->next = head;
        tmp1 = head;
        //这一步非常关键,k太大会导致超时
        k = k % count;
        //头结点为第count-k+1个,使用for循环找到该结点
        for (int i = 0; i < count - k - 1; i++) {
            tmp1 = tmp1->next;
        }
        //改变相应结点的next指针,得到新链表
        head = tmp1->next;
        tmp1->next = nullptr;
        return head;
    }

第141题 环形链表I

要求:判断链表是否有环。

思路一:通过判断结点是否在遍历过程中重复出现来判断是否成环

1)从头开始依次遍历链表,建立unoredered_set,将结点放入set中
2)放入结点前判断结点是否已经存在于set中,若存在则说明成环,直接返回;若不存在则放入
3)若将整个链表遍历完成,仍未发现链表中存在重复结点,则说明链表无环

    //判断链表是否有环
    bool hasCycle1(ListNode* head) {
        unordered_set<ListNode*> s;
        if (!head) return false;
        //从头开始依次遍历链表
        while (head) {
            if (s.count(head))return true;
            s.insert(head);
            //将结点放入set中
            head = head->next;
        }
        //将整个链表遍历完成,仍未发现链表中存在重复结点
        return false;
    }

思路二:使用快慢指针

快慢指针是一种解决链表问题的常用手段,常用于寻找链表的中间结点、链表的环内操作等。

Tip:使用快慢指针找中间结点的方法。

    ListNode* findMid(ListNode* head) {
        ListNode* slow = head, * fast = head;
        while (fast->next != nullptr && fast->next->next != nullptr) {
            fast = fast->next->next;
            slow = slow->next;
        }
        return slow;
    }

1)快慢指针均被初始化为head结点,之后快指针每次往后走两步,慢指针每次往后走一步;
2)若快慢指针会相遇,则说明有环存在。显然,快慢指针在一条非循环单链表中是不可能相遇的。注意:若存在环,则快慢指针一定会在环内相遇,二者互为充要条件。

    bool hasCycle2(ListNode* head) {
        ListNode* fast = head, * slow = head;
        if (head == nullptr || head->next == nullptr)return false;
        while (fast != nullptr && fast->next != nullptr) {
            //快指针每次往后走两步,慢指针每次往后走一步
            fast = fast->next->next;
            slow = slow->next;
            //每走一次都进行判断,若快慢指针相遇,则说明有环存在
            if (fast == slow)return true;
        }
        //若fast指针到了终点,则说明此链表无环
        return false;
    }

思路三:遍历链表,使用标记的思想

1)遍历链表,如果当前结点没有指向它自己,就让它指向自己
2)如果当前结点指向了自己,则说明这个结点之前被操作过,则链表存在环
注意:如果链表只有一个结点,则不可能有环,直接返回

一个很有趣的比喻:假设在森林里有许多棵树,树与树之间有绳子连接,你在森林里沿着绳子一棵棵树往前走,每碰到一棵树就在树上写下自己的名字,如果发现前面那棵树上有自己的名字,即说明存在环。**

    bool hasCycle3(ListNode* head) {
        if (!head || head->next == nullptr)return false;
        //判断当前结点是否指向了自己
        if (head->next == head)return true;
        ListNode* next = head->next;
        //当前结点没有指向自己,就让其指向自己(标记一下)
        head->next = head;
        return hasCycle3(next);
    }

思路四:将链表反转,如果尾结点与头结点一样,则说明有环

在反转链表的函数中,如果遍历到nullptr,则停止。这样会有一个疑惑,循环链表不应该会有nullptr出现,那怎么找到循环链表所谓的反转链表呢?

其实,根据reverseList1函数的思想,最开始我们会让head指向nullptr,在遍历的过程中,很多结点的next指针已经在新链表中发生变化,这样一来遍历的时候出现nullptr就不奇怪了。

举个例子:
例如有这样一个链表,1指向2,2指向3,3指向4,4指向2(开始循环)。(1是头结点)
反转过程:

  1. 初始化一个null,1指向null,2指向1,3指向2,4指向3,那么下一个就会让4指向的结点,来指向4,也就是2指4。
  2. 接下来,next会是cur(2)的next属性,也就是新链表中的1,然后让2指向4,prev为cur也就是2,cur变为新next也就是1。
  3. 再下一次,next值变为cur的next属性,也就是1的next为null,再让1指向2,prev变为1,cur变为null。
  4. 最后,由于cur已经为null,将退出while循环。

这种方法特别巧妙,建议使用断点调试一下整个运行过程,会更加清晰,代码如下(reverseList1())在上文已给出:

    bool hasCycle4(ListNode* head)
    {
        if (head == reverseList1(head)) return true;
        return false;
    }

第142题 环形链表II

要求:在一个存在环的链表中,找到成环的第一个结点。

这道题利用了比较强的算法思想:使用快慢指针时,当二者相遇的时候,相遇结点与成环结点的距离,与头结点到成环结点的距离相等。

分析过程
使用数学方法来简单说明一下:
1)设头结点到成环结点的距离为a,从成环结点沿着next方向到相遇结点的距离为b,从相遇结点沿着next方向回到成环结点的距离为c
2)设相遇时slow指针走了x步,则fast指针走了2x步
3)显然,对于slow指针,x=a+b;对于fast指针,2x=a+b+c+b
4)由此观之,a=c

解题过程

1)使用快慢指针判断是否有环,有环则继续
2)判断有环即为二者相遇,相遇时保持fast的位置,让slow回到head
3)二者同时往前,再次相遇时即为成环的第一个结点

    //检测链表成环的第一个结点
    ListNode* detectCycle(ListNode* head) {
        ListNode* fast = head, * slow = head;
        bool hasCycle = false;
        //使用快慢指针判断是否有环,有环则继续
        while (fast != nullptr && fast->next != nullptr && fast->next->next != nullptr) {
            fast = fast->next->next;
            slow = slow->next;
            if (fast == slow) {
                hasCycle = true;
                break;
            }
        }
        if (hasCycle) {
            //保持fast的位置,让slow回到head
            slow = head;
            //再次相遇时即为成环的第一个结点
            while (slow != fast) {
                slow = slow->next;
                fast = fast->next;
            }
            return slow;
        }
        return nullptr;
    }

第21题 合并两个有序链表

要求:将两个升序链表合并为一个新的升序链表并返回。

解题过程:逐步遍历

1)首先创建虚拟头结点,将其赋值给cur
2)用两个指针分别代表两个链表的结点
3)每次比较当前两个结点的元素大小,得到元素值较小的结点
4)记录该结点的next结点,将该结点放到ans中,取完后将指针移到next结点上,cur结点后移(cur为ans的尾结点)
5)注意:如果有一个链表以及遍历到尾,另一个链表未到尾端,则直接让指针指向未到尾端链表的当前结点,将该链表之后的部分直接移解到ans中

    //合并两个有序链表
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        //创建虚拟头结点
        ListNode* dummy = new ListNode();
        ListNode* cur = dummy;
        while (list1 && list2) {
            //每次比较当前两个结点的元素大小,得到元素值较小的结点
            if (list1->val < list2->val) {
                //将该结点放到ans中
                cur->next = list1;
                //cur结点后移
                cur = cur->next;
                //将指针移到next结点上
                list1 = list1->next;
            }
            //以下同理
            else {
                cur->next = list2;
                cur = cur->next;
                list2 = list2->next;
            }
        }
        //出现了到尾情况,直接“长”链表之后的部分直接移接到ans中
        cur->next = list1 == nullptr ? list2 : list1;
        return dummy->next;
    }

第203题 移除链表元素

要求:给定链表和一个val值,删除值为val的所有结点。

思路一:使用逐步遍历的迭代思想

分析: 使用虚拟头结点,每次碰到当前结点的下一个结点元素值为val,就让该结点指向下下个结点,达到删除结点的目的。

解题过程:
1)创建虚拟头结点dummy,并让其指向head
2)用pre表示当前结点的前一个结点(从dummy开始),用cur表示当前结点(从head开始)
3)当cur值为val时,让pre的next为cur的next,并让将cur的next结点赋值为cur
4)若cur值不为val,则pre与cur均往下走一步,直到cur走到nullptr停止遍历

    //移除链表元素
    ListNode* removeElements1(ListNode* head, int val) {
        //创建虚拟头结点dummy,并让其指向head
        ListNode* dummy = new ListNode(0, nullptr);
        dummy->next = head;
        if (!head) return nullptr;
        //用pre表示当前结点的前一个结点(从dummy开始),用cur表示当前结点(从head开始)
        ListNode* pre = dummy;
        ListNode* cur = head;
        //cur走到nullptr停止遍历
        while (cur) {
            //当cur值为val时,让pre的next为cur的next,并让将cur的next结点赋值为cur
            if (cur->val == val) {
                pre->next = cur->next;
                cur = cur->next;
                continue;
            }
            //若cur值不为val,则pre与cur均往下走一步cur走到nullptr时停止遍历
            pre = pre->next;
            cur = cur->next;
        }
        //最后返回虚拟头结点的next结点作为head
        return dummy->next;
    }

思路二:使用化长为短的递归思想

分析:递归是解决链表问题的常见方法。在这里,如果把当前head之后的链表完成了移除元素的操作,再处理当前的head,即可完成对整个链表操作

1)递归的终止条件:当前结点的值为空
2)递归的单层逻辑:每一次递归,都要把当前结点之后的链表完成移除操作

注意 如果每次递归链表的head结点为空,都需要将head移除,即把head的next结点作为头结点进行返回,达到移除head操作

    ListNode* removeElements2(ListNode* head, int val) {
        //递归的终止条件:当前结点的值为空
        if (!head) return nullptr;
        //把当前结点之后的链表完成移除操作,并将头结点返回给当前的head的next结点
        head->next = removeElements2(head->next, val);
        if (head->val == val)return head->next;
        return head;
    }

第160题 相交链表

要求:给定两个链表,求出二者相交的起始结点,不存在则返回null。

思路一:双指针遍历

让两个指针分别从两个链表头开始遍历,如果二者长度不同,如何才能相遇(在相交结点)?

如果两条链表合在一起就好了!

但是,将二者合并是不现实的,于是,采用一个特殊的方法:双指针逐步遍历,当其到达某条链表的结尾时,让其移到另一条链表头继续遍历。

这样一来,两个指针分别走了两条链表不相交的部分,以及相交的部分各一次(可以理解为各走了三段路),二者步长相同,则会在初次相交的结点相遇。

    //链表的相交结点
    ListNode* getIntersectionNode1(ListNode* headA, ListNode* headB) {
        if (headA == nullptr || headB == nullptr) {
            return nullptr;
        }
        ListNode* pA = headA, * pB = headB;
        while (pA != pB) {
            //当某指针到达某条链表的结尾时,让其移到另一条链表头继续遍历
            pA = pA == nullptr ? headB : pA->next;
            pB = pB == nullptr ? headA : pB->next;
        }
        //相遇时,所在结点即为链表相交结点
        return pA;
    }

思路二:使用set记录

这种方法就比较直接了,同样也易于理解
1)第一次遍历第一条链表,将每个结点记录在set中
2)第二次遍历第二条链表,如果当前结点在set的计数值count为1,说明该结点在第一条链表中出现过,第一个出现过的结点即为相交结点
3)若均不存在,则两条链表不相交

    ListNode* getIntersectionNode2(ListNode* headA, ListNode* headB) {
        unordered_set<ListNode*>first;
        ListNode* temp = headA;
        //第一次遍历第一条链表,将每个结点记录在set中
        while (temp)
        {
            first.insert(temp);
            temp = temp->next;
        }
        temp = headB;
        while (temp)
        {
            //如果当前结点在set的计数值count为1,说明该结点在第一条链表中出现过
            if (first.count(temp)) return temp;
            temp = temp->next;
        }
        //若均不存在,则两条链表不相交
        return nullptr;
    };

第143题 重排链表

要求:给定一个单链表 L 的头节点 head ,单链表 L 表示为:L0 → L1 → … → Ln-1 → Ln,重排后链表变为L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …。

解题思路:找尾结点、切割、反转、合并

1)若链表结点数不超过1,则直接返回
2)找尾结点:不难发现,如果原链表的结点数为奇数,那么重排链表的尾结点为原链表的中间结点;如果为偶数,那么尾结点为原链表的靠左的那个中间结点(中间结点有两个)
3)切割:将得到的尾结点(即中间结点)与原链表的后半部分分开,尾结点指向null,尾结点的原next结点为链表后半部分的头结点
4)反转:将链表后半部分反转,后半部分链表尾结点(也即原链表尾结点)作为后半部分链表的头结点
5)合并,两条链表合并,从将第二条链表插入原链表左半部分

    //重排链表
    void reorderList(ListNode* head) 
{       //链表结点数不超过1,则直接返回
        if (head->next == nullptr || head->next->next == nullptr) return;
        //找中间结点
        ListNode* ans = findMid(head);
        //尾结点的原next结点为链表后半部分的头结点
        ListNode* node2 = ans->next;
        //尾结点指向null
        ans->next = nullptr;
        //反转:后半部分链表尾结点(也即原链表尾结点)作为后半部分链表的头结点
        node2 = reverseList1(node2);
        ListNode* node1 = head;
        //合并,两条链表合并,从将第二条链表插入原链表左半部分,与mergeList()类似
        while (node1 && node2) {
            ListNode* node3 = node2;
            node2 = node2->next;
            ListNode* node4 = node1->next;
            node1->next = node3;
            node3->next = node4;
            node1 = node4;
        }
    }

第148题 相交链表

要求:给定链表,按照升序排列后返回头结点。

解题思路:归并排序

排序算法非常之多,由于链表的特殊性质(按照顺序访问),使用归并排序来解决是个不错的思路,而归并排序本质上使用了递归的思想

1)找到中间结点,其next结点为后半部分链表的头结点
2)分别将左右两个部分排序后,将二者合并(合并函数在前文有提到)

递归的终止条件:该链表的结点数不超过1
递归的单层逻辑:找到中间结点,切割后分别排序,然后合并

    //排序链表
    ListNode* sortList(ListNode* head) {
        if (head == nullptr) {
            return nullptr;
        }
        if (head->next == nullptr) {
            return head;
        }
        //找到中间结点,其next结点为后半部分链表的头结点
        ListNode* mid = findMid(head);
        ListNode* head2 = mid->next;
        mid->next = nullptr;
        //分别将左右两个部分排序后,将二者合并
        ListNode* left = sortList(head);
        ListNode* right = sortList(head2);
        return mergeTwoLists(left, right);
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Leetcode部分经典链表题解析(涉及链表的反转、排序、合并、移除元素、成环、相交等操作) 的相关文章

  • File Browser的安装(适用于Kali/Ubuntu/Debian)

    filebrowser是一个基于Go开发的开源轻量级免费的文件浏览器 xff0c 可以把电脑上的文件快速传到其他设备上 1 下载 下载地址 xff1a https github com filebrowser filebrowser rel
  • Ubuntu 挂载硬盘到 /home 目录下扩容

    实验室提供的 NVIDIA Jetson NX 内存容量太小 xff0c 只有16G xff0c 刷完机装上系统和 CUDA 等安装包后 xff0c 系统只剩下一点多个G xff0c 后面完全是不够用的 xff0c 因此需要加硬盘并挂载才能
  • vue-element-admin 二次开发 报错修改

    安装 GitHub git clone https github com PanJiaChen vue element admin git Gitee https gitee com panjiachen vue element admin
  • 常用字符串函数

    1 strlen 函数 strlen 函数用来计算字符串长度 用法 xff1a 结果 xff1a 2 strcpy 函数 用来将一个数组的内容拷贝到另一个数组 用法 xff1a 结果 xff1a 注意 xff1a 如果a1中的比a2中的长
  • C++ 学习日志——STL中的容器 Vector

    本文简单的介绍下STL下的容器 vector的简单的存放和遍历方法 目录 一 vector存放和访问方式 二 三种遍历方式 三 vector存放对象 四 vector存放指针 难点 一 vector存放和访问方式 迭代器 xff1a vec
  • ARM汇编程序入门实践

    一 stm32程序 1 新建工程 1 xff09 双击打开keil xff0c 点击菜单栏Project gt New Vision Project xff0c 新建项目 xff0c 在弹窗中设置工程项目的名称和路径 xff0c 在这里 x
  • 【STM32学习笔记】(5)—— STM32工程添加源文件和头文件

    向工程目录里创建头文件和源文件 STM32的工程文件构成较为复杂 xff0c 同时为STM32工程文件添加源文件和头文件也是较为复杂的 xff0c 下面就由此文章来介绍怎么给STM32工程添加源文件 xff08 c xff09 与头文件 x
  • 在STM32中使用printf函数

    一 目的 利用printf函数使得输出打印到串口中 二 工作原理 我们在C语言中为什么能够调用printf函数打印数据到控制台中 xff0c 那是因为printf函数又调用了fputc 函数 那么我们我们可不可以说printf函数之所以能够
  • 电赛备赛日记(一):K210与STM32串口通信

    拖更了n久的备赛日记终于来啦 xff0c 最近实现了关于K210图像识别并将所需数据 xff08 即目标类别 xff0c 目标在图像中的加权坐标 xff09 其中 xff0c 加权坐标指K210识别到的目标并框出的框的宽和高与框左上顶点的坐
  • 实验作业2(数组)

    64 TOC实验题目2 xff1a 某公司生产5种产品 xff0c 每周记录生产的每种产品数量和销售数量 每个月月末 xff0c 公司将对其生产规划进行评估 该评估需要以下一个或多个信息 每周生成和销售的数量 xff1b 所有生产产品的总量
  • 函数作业

    仅供交流 xff0c 禁止抄袭 实验一 求序列的和 问题描述 求Y 61 1 1 2 43 1 3 1 4 43 1 2 n 的前n项之和 输入形式 从键盘输入n 输出形式 输出n项和 按四舍五入的方式精确到小数点后第二位 样例输入 30
  • Windows下MySQL安装及配置

    目录 1 MySQL下载2 MySQL配置 mysql版本 xff1a 5 7 注 xff1a 1 现在最新的mysql版本是8 0 xff0c 但是一般安装软件都不推荐安装最新版本的 xff0c 因为可能会有一些错误无法预见 xff0c
  • SLAM遇到的问题及技巧

    文章目录 1 rosbag太大了 xff0c 打不开2 机器人的三维变换roslaunch的node强制关闭了 xff0c exit code 11 1 rosbag太大了 xff0c 打不开 以LZ4格式压缩 rosbag compres
  • 关于螺旋数组的讨论

    下面收集了几种可能的螺旋数组形式以及相应的主代码 供大家学习参考 给定N的值 xff0c 从矩阵的左上角输出顺时针螺旋矩阵 例如N 61 4时 xff0c 输出 xff1a 1 2 3 4 12 13 14 5 11 16 15 6 10
  • 动态链接库dll详解

    动态链接库概述 DLL就是整个Windows操作系统的基础 动态链接库不能直接运行 xff0c 也不能接收消息他们是一些独立的文件 Windows API中的所有函数都包含在DLL中 其中有三个最重要的DLL kernel32 dll xf
  • stm32中printf重定向

    先上代码 加入以下代码 支持printf函数 而不需要选择use MicroLIB if 1 pragma import use no semihosting 标准库需要的支持函数 struct FILE int handle FILE s
  • STM32F103RCTX 串口USART 不定长接收

    串口不定长接收的方法有多种 xff0c 这里我所介绍的是通过设置IDLE中断来检测串口是否接收完毕 xff0c 从而结束串口接受中断 1 首先设置串口 xff0c 如下图所示 xff1a 2 使用IDLE中断检测 xff0c 所以需要开启对
  • ROS通信模式/动作编程(设置收发节点,使小海龟移动到指定位置)以及分布式通信

    文章目录 一 话题 服务模式编程1 1 创建工作空间1 1 1 创建ROS工程包1 1 2 在工作区编译工程包 1 2 话题模式编程1 2 1 创建通信的收 发节点1 2 1 1 在src目录中创建一个发布节点1 2 1 2 在src目录中
  • Ubuntu18.04安装ros(顺利解决 sudo rosdep init 与 rosdep update 存在的问题,附保姆级图文流程)

    Ubuntu18 04 xff08 Ubuntu20 04 xff09 安装ros 顺利解决 sudo rosdep init 与rosdep update 存在的问题 xff0c 附保姆级图文流程 前言 安装了很多次 xff0c 东拼西凑
  • linux命令发送接口请求

    curl k X POST H 34 Accept Encoding gzip deflate 34 H 34 Content type application 34 H 34 x www form urlencoded UTF 8 34

随机推荐

  • UDP协议及编程

    UDP协议 UDP是无连接的 xff0c 即发送数据之前不需要连接 xff0c 因此减少了开销和发送数据之间的时延 UDP使用尽最大努力交付 xff0c 即不保证可靠交付 xff0c 因此主机不需要维持复杂的连接状态表 UDP是面向报文的
  • 24.STM32的IO口扩展PCF8574

    1 IO口扩展芯片 PCF8574是一款带IIC总线 xff0c 可使大多数MCU实现远程I O 口扩展 该器件包含一个8位准双向口和一个IIC总线接口 xff08 通信接口IIC xff0c 2根线可以扩展为8个口 xff09 PCF85
  • 网络编程(二)基础预备知识掌握

    网络编程预备知识 socket 是一种编程接口也是一种文件描述符 xff08 套接字 xff09 可用于 TCP UDP IPX通信 socket的类型 流式套接字 xff08 SOCK STREAM xff09 xff1a 提供一种面向连
  • 使用USTC-TK2016工具对USTC-TFC2016数据集进行处理——报错解决记录

    USTC TK2016数据处理工具 xff1a https github com yungshenglu USTC TK2016 USTC TFC2016数据集 xff1a https github com yungshenglu USTC
  • C++避免头文件重复包含问题

    避免头文件重复包含的方法 xff0c 通常有两种做法 xff1a 条件编译和 pragma once 条件编译就是通常的 ifndef XXX H define XXX H endif ifndef XXX H 表示 xff0c 如果没有包
  • c++ 调用yolov3-yolov4

    ifdef WIN32 define OPENCV define GPU endif include lt iostream gt include lt windows h gt include 34 yolo v2 class hpp 3
  • 一文搞懂UART、RS232、RS485、TTL等常用的接口与协议

    常用的接口与协议 PC机常用的按照接口数量细分为A型 xff08 15针 xff09 xff0c B型 xff08 25针 xff09 xff0c C型 xff08 37针 xff09 xff0c D型 xff08 50针 xff09 xf
  • 解决头文件重复包含与结构体未定义的问题

    一 养成良好的编程习惯 1 保证h文件的纯洁性 xff1a 尽量一个c文件对应一个h文件 xff0c 不要h文件包含许多h文件 这样可以优化编译速度且避免出现h文件中某个结构体之类未定义 xff0c 先在上个h文件中使用的错误 2 对于变量
  • Nokia 5110液晶屏显示模块的使用与开发

    Nokia 5110液晶屏显示模块 我们先来看看他的参数 nbsp 在深入研究连接和示例代码之前 让我们首先看一下其Pinout nbsp RST nbsp 针复位显示 它是低电平有效引脚 您可以通过将其拉低来重置显示 您也可以将此引脚连接
  • mongodb的文档的分页查询

    统计查询使用count xff08 xff09 方法 xff1a 统计comment集合的所有的记录数 xff1a db comment count 分页列表查询 xff1a 可以使用limit xff08 xff09 方法来读取指定数量的
  • 前后端分离项目的部署

    本次项目的项目架构图 xff1a Nginx主要部署的是 项目的静态资源 xff0c 即前端项目 通过Nginx的反向代理 xff0c 将请求发给Tomcat服务器 然后获取数据通过MySQL的主从复制 xff0c 主库负责更新数据 xff
  • echarts基本用法

    目录 tooltip 设置提示框信息 图表的提示框组件 legend 图例组件 toolbox 工具箱组件 可以另存为图片等功能 grid 网格配置 grid可以控制线型图 柱状图 图表大小 xAxs 设置x轴的相关配置 y轴同理 seri
  • java实现UDP通信传输信息

    实现UDP通信要依靠 DatagramPacket对象进行实现 UDP协议的相关介绍 xff1a UDP传输分为 服务端 和客户端 服务端发送消息 客户端接收消息 xff0c 服务端需要知晓客户端的 IP和所监听的端口号 话不多说直接上代码
  • MySQL篇之动态建表。

    在日常开发中 xff0c 可能会出现 动态配置的一些情况 xff0c 此时存储动态配置的一些数据时就需要动态建表了 xff0c 家人们可以选则两种方案 一种是采用mybatis的mapper xml文件里面使用 语句进行创建 二就是使用da
  • IDEA 2020.2 配置Tomcat服务器

    1 创建一个工程 2 右键项目名称 xff0c 选择 add framwork support 3 选中Web Application xff0c 默认勾选创建web xml 目录结构如下 4 点这两个地方中的任意一个 xff0c 添加配置
  • Java笔记之markdown语法

    狂神说Java系列视频笔记 本文章是作者学习B站系列视频 狂神说Java 的记录笔记与心得 xff0c 创作不易 xff0c 希望能够得到您的支持 1 Markdown的基本语法与使用 Markdown是当下一种较为流行的一种写作方法 通过
  • Java之数组专题

    文章目录 Java基础之数组专题数组的定义数组的声明与初始化数组元素的访问内存分析数组的使用For Each 循环数组作方法入参冒泡排序 多维数组稀疏数组 Java基础之数组专题 本文章是作者学习B站系列视频 狂神说Java 与经典书籍 J
  • Java封装详解

    Java类和对象 本文章是作者学习B站系列视频 狂神说Java 与经典书籍 Java核心技术 的记录笔记与心得 xff0c 创作不易 xff0c 希望能够得到您的支持 Java的构造器 Java的构造器 在用Java自定义类时 xff0c
  • C++ primer plus第七章习题中遇到的cin与cin.get问题

    cin gt gt 与cin get 是cpp程序常用到的输入函数 xff0c 近日在编写一道简单的习题时 xff0c 对二者产生了一些疑问 xff08 题目来源 C 43 43 primer plus 中文版习题第七章第六题 xff09
  • Leetcode部分经典链表题解析(涉及链表的反转、排序、合并、移除元素、成环、相交等操作)

    链表相关问题 第206题 反转链表 要求 xff1a 将给定链表进行反转操作 xff0c 第一个结点作为尾结点 xff0c 第二个结点指向第一个节点 xff0c 以此类推 xff0c 使得原链表的尾结点作为答案的头结点 思路一 xff1a