【数据结构】链表OJ第二篇 —— 链表的中间节点 链表中倒数第k个节点 链表分割 链表的回文结构 相交链表

news2024/11/27 2:42:32

文章目录

  • 0. 前言
  • 1. 链表的中间节点
  • 2. 链表中倒数第k个结点
  • 3. 链表分割
  • 4. 链表的回文结构
  • 5. 相交链表
  • 6. 结语

0. 前言

书接上回,我们这次依然是为大家带来链表的OJ题。这一次的题量比之前多一些,内容为链表的中间节点、链表中倒数第k个节点、链表分割、链表的回文结构、相交链表。同样的,我也会使用多种方法和图解来帮助大家更容易理解、吃透这些题目。题目的难度和代码量会有些上升,但是内容也更加丰富,坚持看完,你会有意想不到的收获!话不多说,我们这就开始。

1. 链表的中间节点

链接:876. 链表的中间结点

描述

给定一个头结点为 head 的非空单链表,返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

示例1

输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.

示例2:

输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。

提示

  • 给定链表的结点数介于 1100 之间。

思路1

第一种思路是 暴力求解

题目不是要求链表的中间节点吗?那么我遍历链表,直接算出链表的长度。

对于奇数个节点,那么我返回 长度 / 2的节点当然没问题,且题目要求,如果有两个中间节点,则返回第二个中间节点。那不正好,我偶数个节点时 长度 / 2 就是中间第二个节点,这不就秒了吗(doge)。

image-20221020111841142

但是如果只能遍历一遍呢?我们能用什么方法解决?看思路2↓


思路2(精讲)

这里采用的思路为快慢指针

方法是这样的,给定一个慢指针 slow 一次走一步,快指针 fast 一次走两步。快指针的速度是慢指针的2倍。

当链表的节点数为 奇数 时,快指针走到链表 最后一个节点 停止;当链表的节点数为 偶数 时。快指针走到 空指针 停止。

最后返回的 slow 就是中间节点。

这里的原理其实就是利用了一个差值的原理,当快指针走完链表,那么慢指针恰好走了它的一半,它们走的时间一样,那么慢指针就是中间节点的位置。

image-20221020123204228

image-20221020123349007

2. 链表中倒数第k个结点

链接:链表中倒数第k个结点

描述

输入一个链表,输出该链表中倒数第k个结点。

示例1:

输入:

1,{1,2,3,4,5}

返回值:

{5}

思路1

和求链表的中间节点的方法相似,为直接法。

要求链表的倒数第 k 个节点,那么就是删除链表正数第 len(链表长度) - k + 1 个节点。

举个例子,例如链表长度为 5,删除倒数第 2 个节点,就是删除链表正数第 4 个节点,推导出来就是第 len + 1 - k 个节点。

所以只要先算出链表长度,然后遍历到 len + 1 - k 个节点返回即可。

但是这里需要注意一下区间和迭代关系。

image-20221020124244785

既然这道题目也可以用直接法,那么能否也适用于快慢指针?这当然可以,而且这道题的方法也很巧妙,接下来看思路2↓


思路2(精讲)

又是奇妙的快慢指针,这里大体是这样一个方案。

给定一个快指针 fast 和一个慢指针 slow

我们要求链表倒数第 k 个节点,那么我们就先让快指针走 k 步。

然后让 fastslow 一起走,当 fast 走到空指针,这时 slow 为倒数第 k 个节点。

注意:如果在 fastk 步的过程中,fast 迭代为了空指针,这时直接返回空指针。

那么这里的原理是什么呢?

其实就是首先让 fastk 步,让 fast 和 slow 的间隔为 k。链表的倒数第 k 个节点,就是正数 len + 1 - k 个节点,那么当我 fast 走到空指针后,链表走完,那么现在 fast 走的距离就相当于链表的长度 + 1,fast 和 slow的间隔为 k ,那么现在的 slow 就为正数 len + 1 - k个节点,这时返回 slow就是倒数第 k 个节点。

image-20221020125749412

image-20221020125937113

代码

struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) 
{
    struct ListNode* fast, *slow;
    fast = slow = pListHead;
    if (pListHead == NULL)
        return NULL;
    // fast 先走 k 步
    while (k--)
    {
        // 放置 fast 先走到空
        if (fast == NULL)
        {
            return NULL;
        }
        fast = fast->next;
    }
    // 迭代
    while (fast)
    {
        slow = slow->next;
        fast = fast->next;
    }
    return slow;
}

3. 链表分割

链接:CM11 链表分割

描述

现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。

思路

题目要求我们将小于 x 的节点和大于等于 x 的节点分隔,小于 x 的节点在前,大于等于 x 的节点在后,且不能改变原来的数据顺序。

不能改变顺序就比较棘手,如果没有这个条件,我们可以用双指针来写。但是题目既然给出了要求,我们就得想办法解决。

我们创建一个新链表存放小于 x 的值,另一个存放大于等于 x 的值。然后遍历原链表,将符合条件的值放入对应的链表中,最后再将存放小于 x 的值的链表和存放大于等于 x 的值的链表链接起来

那么这过程肯定是尾插,本题使用哨兵位是十分合适的,因为本题有很多的空指针处理的情况,所以我们设定两个哨兵位 lessHeadgreaterHead

再给定两个尾lessTailgreaterTail,用来尾插。 但是最后记得要释放哨兵位。

请注意,如果以 greaterHead 结束的元素不是链表的最后一个元素(即原链表最后一个元素小于 x ),就可能会造成 链表带环 的情况,需要断开环,然后将 greaterTailnext 置为空。同样的,过会也会画图来讲解。

image-20221107173833002

image-20221107174542665

image-20221020184426339

代码

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) 
    {
        struct ListNode* lessTail, *lessHead, *greaterTail, *greaterHead;
        // 建立哨兵位
        lessTail = lessHead = (struct ListNode*)malloc(sizeof(struct ListNode));
        greaterTail = greaterHead = (struct ListNode*)malloc(sizeof(struct ListNode));
        struct ListNode* cur = pHead;
        while (cur)
        {
            if (cur->val < x)
            {
                lessTail->next = cur;
                lessTail = cur;
            }
            else
            {
                greaterTail->next = cur;
                greaterTail = cur;
            }
            cur = cur->next;
        }
        // 链接两个链表
        lessTail->next = greaterHead->next;
        greaterTail->next = NULL; // 断开环
		// 拷贝节点,释放哨兵位
        struct ListNode* ans = lessHead->next;
        free(lessHead);
        free(greaterHead);
        return ans;
    }
};

这道题目不用哨兵位也可以做,但是比较考验细节,思路大体差不多,有兴趣可以去试试,下面给出截图和代码:

image-20221106202342830

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) 
    {
        struct ListNode* lessTail, *lessHead, *greaterHead, *greaterTail;
        lessTail = lessHead = greaterHead = greaterTail = NULL;
        struct ListNode* cur = pHead;
        while (cur)
        {
            if (cur->val < x)
            {
                if (lessTail == NULL)
                {
                    // 第一次尾插
                    lessHead = lessTail = cur;
                }
                else
                {
                    // 第一次尾插
                    lessTail->next = cur;
                    lessTail = lessTail->next;
                }
                cur = cur->next;
            }
            else
            {
                 if (greaterTail == NULL)
                {
                    greaterHead = greaterTail = cur;
                }
                else
                {
                    greaterTail->next = cur;
                    greaterTail = greaterTail->next;
                }
                cur = cur->next;
            }
        }
        // lessHead 为空,说明原链表为空或链表的值全大于 x
        // 且链表尾部的 next 一定为空
        // 返回 greaterHead
        if (lessHead == NULL)
            return greaterHead;
        // 如果 lessHead 和 greaterHead 都不为空
        // 说明正常分割
        // 将其链接,greaterHead 尾部链空
        if (lessHead != NULL && greaterHead != NULL)
        {
            lessTail->next = greaterHead;
            greaterTail->next = NULL;
        }
        // 无论是正常分割,还是链表的值全小于 x
        // 都是返回 lessHead
        return lessHead;
    }
};

4. 链表的回文结构

链接:OR36 链表的回文结构

描述

对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。

给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。

示例

测试样例:1->2->2->1
返回:true

思路

如果不加空间复杂度为O(1)的限制的话,那么我们可以创建一个数组,然后遍历链表,将链表中元素放到数组中,从数组前后开始遍历,判断是否是回文结构。

但是这里已经给定了要求,那我们便最好不要使用这种写法,所以我们要重新设计一个方法。

我们仔细想想,链表的回文结构,不就是从头开始向后遍历的元素和从后向前遍历的元素遍历到中间位置相等吗?

那么我们找到中间节点 mid,然后将 mid 开始的链表反转,将这个链表的起始节点给定为 reHead。然后奇偶情况遍历链表不就可以了吗?接下来我们展开讨论:

我们假定 reHead 已经反转,给定 curR来遍历 reHead,给定 curA 遍历 原链表

原链表为奇数个节点curA、curR 同时开始走, reHead 先走完,当 curA 走到 reHead前一个节点 时,并不会走到 rehead 。因为原链表的结构并没有改变,所以会走到原链表的下一个位置。所以不用担心 reHead 反转后链表表面上改变,而导致回文结构辨识不出的情况。(这样说可能有些模糊,但是没关系,马上有图解)

原链表为偶数个节点curA、curR同时开始走,reHead先走完。这里由于 reHead 前和从 reHead 开始的节点个数相等,所以也就不需要想那么多。

结论:无论奇数偶数,只要 curAcurR 中有一个走到空就停止。

所以我们可以归纳一下这里的步骤:找中心节点 -> 反转中心节点开始的链表 -> 迭代判断

而这里非常巧的是,我们上篇博客中已经写过了前两步——链表的中心节点、反转链表,所以到时候直接搬运即可~

image-20221107175342247

image-20221020160203086

image-20221020143728372

:C++兼容C的语法,所以用C的语法写完全可以。而且这道题目在力扣上没有限制空间复杂度,所以采用牛客网的~

代码

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/

struct ListNode* middleNode(struct ListNode* head)
{
    struct ListNode* fast, *slow;
    fast = slow = head;

    while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
    }
    return slow;
}

struct ListNode* reverseList(struct ListNode* head)
{
    struct ListNode* cur = head;
    struct ListNode* newNode = NULL;
    while (cur)
    {
        struct ListNode* next = cur->next;
        // 头插
        cur->next = newNode;
        newNode = cur;

        // cur迭代
        cur = next;
    }

    return newNode;
}

class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        struct ListNode* mid = middleNode(A);
        struct ListNode* rHead = reverseList(mid);

        // A和rHead一般不会直接使用,拷贝一份
        struct ListNode* curA = A;
        struct ListNode* curR = rHead;

        while (curA && curR)
        {
            if (curA->val != curR->val)
            {
                return false;
            }
            curA = curA->next;
            curR = curR->next;
        }
        return true;
    }
};

5. 相交链表

链接:160. 相交链表

描述

给你两个单链表的头节点 headAheadB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null

图示两个链表在节点 c1 开始相交:

img

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。

自定义评测

评测系统 的输入如下(你设计的程序 不适用 此输入):

  • intersectVal - 相交的起始节点的值。如果不存在相交节点,这一值为 0
  • listA - 第一个链表
  • listB - 第二个链表
  • skipA - 在 listA 中(从头节点开始)跳到交叉节点的节点数
  • skipB - 在 listB 中(从头节点开始)跳到交叉节点的节点数
    评测系统将根据这些输入创建链式数据结构,并将两个头节点 headAheadB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案

示例1

img

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at ‘8’
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,6,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
— 请注意相交节点的值不为 1,因为在链表 A 和链表 B 之中值为 1 的节点 (A 中第二个节点和 B 中第三个节点) 是不同的节点。换句话说,它们在内存中指向两个不同的位置,而链表 A 和链表 B 中值为 8 的节点 (A 中第三个节点,B 中第四个节点) 在内存中指向相同的位置。

示例2

img

输入:intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at ‘2’
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [1,9,1,2,4],链表 B 为 [3,2,4]。
在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

示例3

img

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。
由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
这两个链表不相交,因此返回 null 。

提示

  • listA 中节点数目为 m
  • listB 中节点数目为 n
  • 1 <= m, n <= 3 * 10^4
  • 1 <= Node.val <= 10^5
  • 0 <= skipA <= m
  • 0 <= skipB <= n
  • 如果 listAlistB 没有交点,intersectVal0
  • 如果 listAlistB 有交点,intersectVal == listA[skipA] == listB[skipB]

思路1

如果要说这道题目,如果不考虑任何方法,那么就直接 暴力求解

取其中一条链表,让它的所有节点和另一条链表的所有元素比较。判断是否有交点,有则返回该节点;链表遍历完没有交点的话,返回空指针。

而且这次也出奇的巧,暴力求解在力扣上也能跑过~

image-20221020190124296

但是在速度方面就很难看了,那我们能不能做出一些优化?看思路2↓


思路2(精讲)

首先,我们要明确的一点是,只要两条链表 有交点 ,那么这两条链表的 尾结点 就是相等的。

因为单链表中存储的一部分是数据,一部分是下一个节点的地址,一个节点中只有一个 next ,所以以后链表走的都是一条路。

就像这样:

image-20221107175722627

所以如果两个链表相交,就说明它们的 尾结点 肯定相同,那么遍历两条链表,比较它们的尾。

然后算出两条链表的长度,让长的链表走差值步。

那么让我长链表先走差值步,走到和短链表一样长,然后一起走,肯定就能找到交点了呀!找到交点后返回长链表、短链表节点中的任意一个。

注意点(已踩坑)

当我们求长链表和短链表时,如果使用了三目操作符,比如:

 struct ListNode* longList = lenA > lenB ? headA : headB;
 struct ListNode* shortList = lenA < lenB ? headA : headB;

如果这样写,大多测试用例都能跑过,但是如果碰上一组两条链表的值相等的情况:

相交点 intersectVal:4

headA:②→③→④→⑤

headB:②→③→④→⑤

这样那么 longList 和 shortList 都是 headB,那么求相交点时,就直接返回第一个节点②了。

所以要控制 条件相同 ,让 longList 和 shortList 为不同的链表。

比如这样:

 struct ListNode* longList = lenA > lenB ? headA : headB;
 struct ListNode* shortList = lenA > lenB ? headB : headA;

注:可能是因为博主太菜,在这道题目 n 刷时,突然这么写了,找了半天没发现错误…希望大家不要踩坑…

image-20221107180023388

image-20221107183948441

代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    struct ListNode* tailA = headA;
    struct ListNode* tailB = headB;
    int lenA = 1, lenB = 1;
    // 这里 lenA 和 lenB 初始值其实关系不大
    // 主要是算它们的差值,所以即使 lenA 和 lenB初始化为 0 也能跑过
    // 但是由于是遍历到尾,所以 lenA 和 B 初始化为1是真正算出链表长度的
    while (tailA->next)
    {
        ++lenA;
        tailA = tailA->next;
    }
    while (tailB->next)
    {
        tailB = tailB->next;
        ++lenB;
    }
    if (tailA != tailB)
    {
        return NULL;
    }  
    struct ListNode* longList = lenA > lenB ? headA : headB;
    // 这里需要注意一下,两次三目表达式的条件最好一样
    // 否则链表的值相同时,可能会选取同一个链表
    // 导致结果错误,已踩坑
    struct ListNode* shortList = lenA > lenB ? headB : headA;

    int gap = abs(lenA - lenB);// 求差值
    
    while (gap--)
    {
        longList = longList->next;    
    }
    
    while (longList != shortList)
    {
        longList = longList->next;
        shortList = shortList->next;
    }
    
    return longList;
}

6. 结语

到这里本篇博客就到此结束了,这次的题目还是比较麻烦的,如果没完全理解可以画画图,多看看,多写写。

在下期,我依旧会为大家来带链表的OJ题,但是形式会和前两篇不太一样,我会用小剧场的形式,帮助大家在互动中带大家吃透链表中经典的问题!剧透一下,下一期内容会很精彩!我们敬请期待~

如果觉得anduin写的还不错的话,还请一键三连!如有错误,还请指正!

我是anduin,一名C语言初学者,我们下期见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/4104.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安卓讲课笔记5.2 编辑框

文章目录零、本讲学习目标一、导入新课二、新课讲解&#xff08;一&#xff09;继承关系图&#xff08;二&#xff09;编辑框常用属性&#xff08;三&#xff09;教学案例&#xff1a;用户注册1、创建安卓应用2、准备图片素材3、主界面与主布局资源文件更名4、创建息界面类5、字…

数据获取与预处理

文章目录Requests简介Requests库安装Requests库的基本操作Requests库的7个主要方法Request方法get方法Response对象的属性head方法post方法Requests简介 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 首先他是个第三方库&#xff0c;应用非常广泛 采用Apac…

《数据结构》(六)八大排序(下)

承接上篇的八大排序&#xff0c;今天本篇文章主要讲归并排序&#xff0c;冒泡排序&#xff0c;快速排序(挖坑&#xff0c;左右指针&#xff0c;前指针)和计数排序 八大排序交换排序冒泡排序冒泡排序思想代码冒泡排序总结快速排序快速排序思想三数取中快速排序之挖坑法挖坑法代码…

量化股票查询代码是什么?

量化股票查询代码是什么&#xff1f;接下来用一些代码来分析一下&#xff0c;如下&#xff1a; 做空95&#xff1a;HHV((HIGHLOWOPEN2*CLOSE)/5H-L,5),COLORBLUE;做空68: HHV((HIGH-LOWOPEN2*CLOSE)/5*2-L,5),COLORRED&#xff1b; 平衡点&#xff1a;LLV((HIGHLOWOPEN2*CLOSE…

狗厂员工来面试本想难为一下,问他内存溢出,结果被虐得连console.log也不敢写了

这次说到的面试题是关于node服务端内存溢出的问题&#xff0c;狗厂员工来面试本想难为一下&#xff0c;现在我连console.log也不敢写了 关于这道node内存溢出的问题&#xff0c;大哥从以下几个方面讲的&#xff0c;讲完我觉得自己得到了升华&#xff0c;现在搞得连代码也快不敢…

AI人脸检测/安全帽检测智能分析网关告警消息配置——微信告警消息配置

AI智能分析网关内置多种深度学习算法&#xff0c;可支持对接入的多路视频流进行智能检测、智能识别等&#xff0c;包括人脸检测与识别、车辆检测与识别、车牌识别、烟火识别、安全帽识别、区域入侵检测等。将智能分析网关与EasyCVR视频融合平台联合使用&#xff0c;可实现智能告…

Linux命令从入门到实战 ---- 用户管理命令

文章目录useradd添加新用户passwd设置用户密码id查看用户是否存在查看创建了哪些用户su切换用户userdel删除用户who查看登录用户信息sudo设置普通用户具有root权限用户组groupadd 新增用户组usermod修改用户groupdel删除用户组groupmod修改用户组总结useradd添加新用户 将usera…

安卓学习笔记5.3 按钮、图像视图与图像按钮

文章目录零、本讲学习目标一、导入新课二、新课讲解&#xff08;一&#xff09;按钮控件1、继承关系图2、常用属性&#xff08;二&#xff09;图像视图1、继承关系图2、常用属性&#xff08;三&#xff09;图像按钮1、继承关系图2、常用属性&#xff08;四&#xff09;教学案例…

vue无需改动代码的SEO【百度爬取】优化--puppeteer(详细流程)

vue无需改动代码的SEO优化–puppeteer&#xff08;详细流程&#xff09; 目录vue无需改动代码的SEO优化--puppeteer&#xff08;详细流程&#xff09;一级目录二级目录三级目录一、安装puppeteer&#xff1a;npm install puppeteer --save安装依赖二、编写puppeteer服务js文件p…

DDD领域驱动设计基础

什么领域驱动模型 领域驱动模型一种设计思想&#xff0c;我们又称为DDD设计思想。是一种为了解决传统设计思想带来的维护困难&#xff0c;沟通困难和交互困难而产生的一种新的思想。 架构模式的演进 单体架构 采用面向对象的设计方法&#xff0c;系统包括业务接入层、业务逻…

Eclipse切JRE环境后如何恢复- Unrecognized option: --enable-preview

场景 使用switch 新特性 配合 lambda 练习小案例 // 需求&#xff1a; 1 2 3 -> 一、二、 三 int num 1; switch ( num) {// jdk13 可以缺省 break 并且 单语句可以省略 花括号 case 1 -> { System.out.println("一"); }case 2 -> System.out.p…

[附源码]计算机毕业设计JAVAjsp宠物店管理系统

[附源码]计算机毕业设计JAVAjsp宠物店管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybat…

Mybatis-Plus知识点[MyBatis+MyBatis-Plus的基础运用]

目录 前言 一、了解Mybatis-Plus 1.简介 2.Mybatis-Plus具有的特性 3.支持数据库 4.框架结构 5.官网链接 二、快速开始 2.1.创建数据库以及表 2.2.创建工程 2.3 MybatisMybatis-Plus的使用 2.3.1创建一个itcast-mybatis-plus-simple的maven项目 2.3.2写UserMapper接口 2.3.3写U…

北京化工大学数据结构2022/11/3作业 题解

目录 问题 A: 二叉树非递归前序遍历-附加代码模式 问题 B: 二叉树非递归中序遍历-附加代码模式 问题 C: 二叉树非递归后序遍历-附加代码模式 问题 D: 求二叉树中序遍历序根节点的下标 问题 E: 根据前序中序还原二叉树 问题 F: 算法6-12&#xff1a;自底向上的赫夫曼编码 …

ServletConfig和ServletContext接口

一、ServletConfig接口详解 1、简介 Servlet 容器初始化 Servlet 时&#xff0c;会为这个 Servlet 创建一个 ServletConfig 对象&#xff0c;并将 ServletConfig 对象作为参数传递给 Servlet 。通过 ServletConfig 对象即可获得当前 Servlet 的初始化参数信息。一个 Web 应用中…

微电网优化调度(风、光、储能、柴油机)(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; ​ &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻…

【Linux命令】文件和目录权限

【Linux命令】文件和目录权限 权限查看 众所周知&#xff0c;可以使用 ls -l 来查看文件和目录的详细信息&#xff0c;那么输出的东西是什么呢&#xff1f; 我们先来看 文件类型&#xff1a; -&#xff1a;普通文件&#xff1b;d&#xff1a;目录文件&#xff1b;b&#xff…

网络协议:TCP三次握手与四次挥手

本篇内容包括&#xff1a;TCP/IP 传输协议&#xff08;TCP/IP 传输协议简介&#xff0c;IP 协议&#xff0c;UDP 协议&#xff0c;TCP 协议介绍&#xff09;&#xff0c;TCP 的三次握手、TCP 的四次挥手 以及 TCP 协议是怎么保证有效传输等内容。 一、TCP/IP 传输协议 1、TCP/…

【仿牛客网笔记】 Redis,一站式高性能存储方案——Redis入门

Redis可以开发对性能要求较高的功能。还可以利用Redis重构我们现有的功能。 NoSQL关系型数据库之外的统称。 快照有称为RDB 以快照的形式 不适合实时的去做&#xff0c;适合一段时间做一次。 日志又称AOF 以日志的形式每执行一次就存入到硬盘中&#xff0c;可以做到实时的存储以…

JAVA外卖订餐系统毕业设计 开题报告

本文给出的java毕业设计开题报告&#xff0c;仅供参考&#xff01;&#xff08;具体模板和要求按照自己学校给的要求修改&#xff09; 选题目的和意义 目的&#xff1a;本课题主要目标是设计并能够实现一个基于java的外卖点菜系统&#xff0c;管理员通过后台添加菜品&#xf…