好题分享(2023.11.5——2023.11.11)

目录

前情回顾:

前言:

题目一:补充《移除链表元素》

题目二:《反转链表》

解法一:三指针法

解法二:头插法 

题目三: 《相交链表》

题目四:《合并两个有序数列》

题目五:《链表中倒数第K个节点》

题目六:《链表的分割》

题目七:《链表的回文结构》 

题目八:《环形链表(一)》 

 题目九:《环形链表(二)》 

由题目八引出结论:

对于第九题的算法:

总结:

题目十:《随机链表的复制》

1.先拷贝各个节点,再连接起来

2.对random进行赋值

3.断开连接

总结:


前情回顾:

我们在上一篇好题分析中,分析了以下几题:

《合并两个有序数组》《移除链表元素》《链表的中间节点》

上一篇的好题分析的blog在

好题分析(2023.10.29——2023.11.04)-CSDN博客

前言:

本次好题分享,我们将对《移除链表元素》进行一种算法即思路进行补充,因为在之后的题目,都是围绕此算法来实现的

同时,我们还将对Leecode和牛客网上的众多题目进行分析:

《反转链表》《相交链表》《环形链表(一)》《环形链表(二)》《随机链表的复制》《合并两个有序链表》

《链表中倒数第K个节点》《链表分割》《链表的回文结构》

题目一:补充《移除链表元素》

 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

​ 

我们在上一篇blog中,我们是利用三个指针来进行操作,在删除节点前,保存该节点前后的节点,再进行修改指向的操作,此算法的不足之处,就在于如果我们要删除的元素位于头结点,那么这个时候就要考虑另外一种情况了。

接下来的算法将可以省去上述步骤,且在之后的刷题中会更高效!

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 
 //创建“新链表”
struct ListNode* removeElements(struct ListNode* head, int val) {
    struct ListNode* newhead = NULL,*cur = head,*tail = NULL;
    while(cur)
    {
        //不是val节点的拿下来尾插
        if(cur->val != val)
        {
            //尾插
            if(tail==NULL)
            {
                newhead = tail =cur;
            }
            else
            {
                tail->next = cur;
                tail = tail->next;
            }
            cur = cur->next;
        }
        else
        {
            cur =cur->next;
        }
    }
    if(tail)
    {
        tail->next = NULL;
    }
    return newhead;
}

 该算法是先创建一个新链表,将需要的节点连接到新链表中,再返回新创建的指针。

 刚开始由于newnode指向的是NULL,即该链表为空,所以我们需要进行尾插操作,同时tail也指向新链表的第一个节点。

即:

但是要注意的是,此时我们newnode中的头结点,它的next是指向原链表中所在位置的下一个节点的,并非指向NULL,即:

​ 

你可能会觉得代码中该部分是多余的

​ 

但是这一步缺失这种算法的关键。

如果我们这时候的cur指向了题目描述中的val,此时cur就会跳过该节点。

并指向下一个节点,那么如果没有tail->next = cur;这一行代码

那么新链表中的tail将直接指向题目描述中的val。

所以我们必须加上此代码!!! 

当遇到此时的情况时,如果我们直接放回newnode,就会是一个不完整的链表,因为尾结点并没有指向NULL,所有我们务必要在最后加上一句:tail->next = NULL;

 这种创建新链表的思想需要我们去学习,在之后的题目中尤为重要!

题目二:《反转链表》

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

对于本题目我将给出两种算法,为了展示出创建新链表该种算法的优势。 

解法一:三指针法

 如果我们尝试常规解法来实现,那我们我们就务必需要保存前后节点的位置。

所以该算法实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 
 //三指针法
struct ListNode* reverseList(struct ListNode* head) {
    if(head==NULL)
    {
        return NULL;
    }
    
    struct ListNode* n1 = NULL,*n2 = head,*n3 = head->next;
    if(n3 == NULL)
    {
        return n2;
    }

    while(n2 != NULL)
    {
        n2->next = n1;
        n1 = n2;
        n2 = n3;
        if(n3)
            n3 = n3->next;
    }
    return n1;
}

​ 

​ 

​ 

这道题还要注意,如果链表只要一个节点或者无节点时的返回值!

解法二:头插法 

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

 //头插法
struct ListNode* reverseList(struct ListNode* head) {
    if(head == NULL)
    {
        return NULL;
    }

    struct ListNode* newnode = NULL;
    struct ListNode* cur = head;
    struct ListNode* next = head->next;
    
    while(next)
    {
        cur->next = newnode;
        newnode = cur;
        cur = next;
        next = next->next;
    }
    cur -> next = newnode;
    newnode = cur;
    return newnode; 

}

 

反转的本质,就是在新链表中头插 。

那么我们就可以将cur->next指向newnode;

newnode再指向此时的cur,这就完成了头插操作

再将cur = next,

next = next -> next;

因为我们改变来cur->next的指向,所以我们对于保存cur下一个节点的位置就尤为重要!

​ 

完成操作后,我们最好可以将head = NULL,避免出现野指针。

题目三: 《相交链表》

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode* curA = headA, *curB = headB;
    int countA = 0;
    int countB = 0;
    //判断是否相交
    while(curA->next)
    {
        curA = curA->next;
        countA++;
    }   

    while(curB->next)
    {
        curB = curB->next;
        countB++;
    }   
    if(curA != curB)
    {
        return NULL;
    }

    //找出相交的起始节点
    int n = abs(countA - countB);
    if(countA > countB)
    {
        while(n)
        {
            headA = headA->next;
            --n;
        }
        while(headA != headB)
        {
            headA = headA->next;
            headB = headB->next;
        }
        return headA;
    }
    else
    {
        while(n)
        {
            headB = headB->next;
            --n;
        }
        while(headA != headB)
        {
            headA = headA->next;
            headB = headB->next;
        }
        return headB;
    }


}

对于该题目,我们提供一种算法:

1.先判断它们是否相交。

2.找到第一个公共节点。

相交好判断

我们可以先遍历,找到它们最后一个节点,如果节点相同,就说明它们相交!

因为相交链表只能是“Y”型相交,而绝对不可能是“X”型的 !

那么对于第二步,

我们可以先求出两个链表分别有多长,再相减求绝对值,得出相差步。

再使得短的链表的curA先走相差步,这样两个指针就是从同一位置起步了

再一起同时走一步,直到它们相等,如果这时两指针相等,则就说明相等的节点就是第一个公共节点!

让curB走向差步:

​ 

在同时走一步:

​ 

如此就可以得到公共节点!

题目四:《合并两个有序数列》

 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

​ 

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) 
{
    struct ListNode* cur1 = list1,*cur2 = list2;
    struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
    newnode->next = NULL;
    struct ListNode* next = NULL;
    struct ListNode* tail = newnode;
    while(cur1 && cur2)
    {
        if((cur1->val <= cur2->val))
        {
            next = cur1->next;
            tail->next = cur1;
            cur1 = next;
            tail = tail->next;
        }
        else
        {
            next = cur2->next;
            tail->next = cur2;
            cur2 = next;
            tail = tail->next;
        }
    }
    if(cur1==NULL)
    {
        tail->next = cur2;
    }
    else
    {
        tail->next = cur1;
    }
    return newnode->next;
}

对于该题目,我建议使用新链表法,同时我们最好创建一个哨兵位的头结点。

具体为什么我这里建议使用新链表法,想要反驳的同学下去可以自己动手创建一个无哨兵位的解法,相信你一定会被绕晕的。

鉴于我们已经学会了前面两道题目的算法,这道题相信大家一定很好理解!

​ 

 

 

如此循环,当cur1或者cur2为NULL时,则直接让tail->next指向cur1或cur2.

即:

题目五:《链表中倒数第K个节点》

 链表中倒数第k个结点_牛客题霸_牛客网

 

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */

/**
 * 
 * @param pListHead ListNode类 
 * @param k int整型 
 * @return ListNode类
 */
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
    // write code here
    if(pListHead == NULL)
    {
        return NULL;
    }

    int count = 0;
    struct ListNode* tmp = pListHead;
    while(tmp)
    {
        count++;
        tmp = tmp->next;
    }

    int n = count - k;
    if(n<=0 && k > count)
    {
        return NULL;
    }
    while(n--)
    {
        
        pListHead = pListHead->next;
    }
    return pListHead;

}

该题目的算法实现还是好理解 

我们先统计该链表存在多少个节点。

然后再减去所谓的倒数第K个。

就可以得到正数第几个n,

再将pListHead进行遍历,同时n--

再返回此时的pListHead

思路还是好理解的,在这里我就不进行画图展示了。

题目六:《链表的分割》

链表分割_牛客题霸_牛客网

​ 

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
#include <cstddef>
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x)
     {
        // write code here
        struct ListNode* head1,*tail1,*head2,*tail2;
        head1 = tail1 = (struct ListNode*)malloc(sizeof(struct ListNode));
        head2 = tail2 = (struct ListNode*)malloc(sizeof(struct ListNode));
        struct ListNode* cur = pHead;
        while(cur)
        {
            if(cur->val<x)
            {
                tail1->next = cur;
                tail1 = tail1->next;
                
            }
            else 
            {
                tail2->next = cur;
                tail2 = tail2->next;
            }
            cur= cur->next;
        }

        tail1->next = head2->next;
        //防止成环
        tail2->next = NULL;
        pHead = head1->next;
        free(head1);
        free(head2);
        return pHead;
    }
};

 对于该题目的算法思路,要注意的有以下几点:

1.我们在此选择开辟两个哨兵位的头节点创建链表,小于等于x的到第一个链表,大于x的到第二个链表。

2.再将小链表的最后一个节点的next,链接到第二个哨兵位头节点的next。

3.同时还要注意成环问题!

 

如此一直循环:

​ 

到这里时我们就可以直接将tail1->next = head2->next;

即:

此时一定不要忘记将tail2->next = NULL;

因为此时的tail2->next是指向的tail1指向的节点的

​ 

如果这里不注意的话,就会形成一个环!!!

​ 

如此才是正确的全部思路。

题目七:《链表的回文结构》 

链表的回文结构_牛客题霸_牛客网

 

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        // write code here

        //找中间节点
        ListNode* fast = A;
        ListNode* slow = A;
        while(fast && fast->next)
        {
            fast = fast->next->next;
            slow = slow->next;
        }

        //逆序
        ListNode* next = slow ->next;
        ListNode* rehead = slow;
        rehead->next = NULL;
        while(next)
        {
        slow = next;
        next = slow->next;
        slow->next = rehead;
        rehead = slow;
        }

        while(A && rehead)
        {
            if(A->val == rehead->val)
            {
                A = A->next;
                rehead = rehead->next;
            }
            else
            {
                return false;
            }
        }
        return true;
    }
};

 由于牛客网对于本题目只要C++一种格式,但是没关系,C++兼容C语言。

所有我们就按照我们的写法即可:

 

第一步,利用快慢指针找到中间节点!

即:

​ 

此时的该节点就为中间节点。

再逆序中间节点后面的全部节点

利用新链表法!

先创建个指针rehead

​ 

在创建的时候,提前将slow指向的节点拿下来,进行置空操作,即:

 再进行一个经典的头插操作即while循环里面的全部操作:

如此就可以进行全部逆序的操作,则此时的图为:

​ 

我们只需要分别将A和rehead每次挪动一步,再判断是否为相等即可。

如果一直相等直到循环结束,就return true

如果出现不想等的,直接return false

题目八:《环形链表(一)》 

 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode *head) {
    struct ListNode* fast,*slow;
    fast = slow = head;
    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if(fast == slow)
        {
            return true;
        }
    }
    return false;
}

对于一个带环链表,我们遇到该种题目应当先考虑考虑快慢指针算法。

如图:

fast一次走两步,slow一次走一步,当它们相遇的时候,一定是在圆环内!

例:

从上述可以看出,再进行第三次循环的时候,fast和slow就相遇,就说明此时的链表是带环链表。

 题目九:《环形链表(二)》 

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode* fast = head, *slow = head;
    struct ListNode* meet = NULL;
    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if(fast == slow)
        {
            meet = slow;
            while(head != meet)
            {
                head = head->next;
                meet = meet->next;
            }
            return head;
        }
    }

    return NULL;
}

这道题与上题类似,但区别在于现在已经告诉你这是一个环形链表,需要你求出进入环的第一个节点。

对于解决该问题的方法,此方法偏向于数学思维思路。

我们由图来分析。

由题目八引出结论:

 我们在题目八中分析过,如果我们利用快慢指针,就可以求出它们是否再圆环内。

但是当快指针一次走三步呢?

那么还可以追上吗?

这就不得不利用数学思维来解决此问题。

 

我们可以将链表抽象为如图内容。

那么当fast一次三步时,怎么判断它们是否相遇:

当slow刚进入环内时,fast肯定比slow快3倍,走过的距离肯定也多三倍。

但是一旦它们都在环内时,距离就会一直-2.

假设一开始的距离为n

此时的-1就代表了它们的距离相差1,意思就是:

那么就不难的出以下结论:

假设C为圆的周长,此时它们距离就是C-1。

如果C-1为偶数,那么随着它们-2的操作,最后会相遇。

但如果C-1是奇数,那么随着它们-2的操作,最后还需要再来一圈才可以相遇!

即:

1.若n为偶数,直接就可以追上

2.若n是奇数,C是奇数,得过两圈才能追上。

3.如果n是奇数,C是偶数,永远都追不上。

但是第3条是不成立的,因为我们可以得出公式:

L为直线长

N是两指针在刚开始的距离,

3L = L +n*C - N

即2L = n*C - N

等号左边百分百为偶数,

而右边永远等于奇数。

所以它们不相等,即该结论永远不成立!

对于第九题的算法:

 而对于该题目,我们只需要知道此时的fast只走一步,而它们绝对可以在圆环内相遇:

我们在它们相遇的地方创建个指针,指向该地方,后面我们就会用到此指针:

我们在创建个未知数X,代表第一个环节点到相遇点, 

 通过该图,我们可以知道,slow走过的路程 = fast的路程/2

所以就有2(L+X) = L + X + n*C

假设这个环足够小,那么我的fast很有可能在圆环内走很多圈,但我们假设就走过一圈。

则就有以下算式:

2(L+X) =L + X + C

L = C - X

通过以上的推导:

我们知道了以下:

L== Y

那我们就可以让meet和head同时走一步,直到它们相遇,因为相遇的地方就是圆环的第一个节点。

这样就可以求出来第一个节点了!

总结:

本题目设计到的数学思维和思路会使很多同学绕不清楚,还有转不过弯来。

对于这部分的解法下来需要好好熟练掌握并学习学习,在这里我就不再多讲了。

题目十:《随机链表的复制》

 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */

struct Node* copyRandomList(struct Node* head) {
     if (head == NULL) {
        return NULL;
    }

	struct Node* cur = head;
    struct Node* copy = NULL;
    while(cur)
    {
        copy = (struct Node*)malloc(sizeof(struct Node));
        copy->val = cur->val;
        copy->next = cur->next;
        cur->next = copy;
        cur = cur->next->next;
    }
    copy = head->next;
    struct Node* tmp = NULL;
    cur = head;
    while(cur)
    {
        tmp = cur->next;
        tmp->random = (cur->random != NULL)?cur->random->next : NULL;
        cur = cur->next->next;
    }

    tmp = copy;
    while(tmp->next != NULL)
    {
        tmp->next = tmp->next->next;
        tmp = tmp->next;
    }
    return copy;
}

本道题目较难,我在这里先讲解以下思路:

1.先拷贝各个节点,再连接起来

2.对random进行赋值

 这里格外要注意,如果此时原radom是NULL,就要另外讨论。

如果不为空,则将cur->radom->next赋给copy

这一句代码则是精华所在!

3.断开连接

 将拷贝好的各个节点互相链接,并且返回。

总结:

本周的好题分享设计到的知识面较广,我们在做题过程中难免会遇到一些难以实现的操作,但是只要我们沉下心来一点点的了解和学习,相信一定会有进步!

记住“坐而言不如起而行!”

Action speak louder than words!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【原创】java+swing+mysql办公用品管理系统设计与实现

摘要&#xff1a; 办公用品管理系统是一个设计和实现办公用品库存和使用管理的信息系统。此系统可以提高办公用品的利用率&#xff0c;减少浪费&#xff0c;使办公用品管理更加高效、规范、便捷。本文主要介绍使用javaswingmysql技术去开发实现一个办公用品管理系统。 功能分…

若依侧边栏添加计数标记效果

2023.11.13今天我学习了如何对若依的侧边栏添加技术标记的效果&#xff0c;如图&#xff1a; 我们需要用到两个页面&#xff1a; 先说子组件实现计数标记效果 1.item.vue <script> export default {name: MenuItem,functional: true,props: {icon: {type: String,defau…

【网络豆送书第六期】《嵌入式虚拟化技术与应用》

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 公众号&#xff1a;网络豆云计算学堂 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a; 网络豆的主页​​​​​ 本期好书推荐&#xff1a;《嵌入式虚拟化技术与应用…

使用代理IP时有哪些小技巧?大数据技术人员必看

很多大数据行业和跨境行业的用户都会使用到一个工具&#xff0c;就是代理IP工具&#xff0c;不过很多人对它的研究不深&#xff0c;其实在使用它时是有一些小技巧的&#xff0c;它不仅可以帮助我们隐蔽我们的真实IP地址&#xff0c;实现多账号矩阵运营&#xff0c;同时还能让我…

告别瞎忙+拖延,工作中必不可少的便签工具

在平常的工作中&#xff0c;很多人都会感慨&#xff0c;每天的工作都是在瞎忙&#xff0c;一天忙忙碌碌结束后发现仍旧有许多待完成的任务&#xff0c;也有一些人在工作中碌碌无为&#xff0c;消极怠工拖延时间&#xff0c;瞎忙拖延归根到底是没有提前将工作中的各项工作安排妥…

双十一大促已过,虾皮、Lazada年底如何通过测评补单打造搜索排名

双十一大促已过&#xff0c;有人欢喜有人忧&#xff0c;不管怎么样&#xff0c;年底的这波旺季还是要好好把握的。 如何提升虾皮搜索排名 1、标题关键词匹配度 Shopee、Lazada的排名规则主要是根据用户搜索时输入的关键字和卖家的商品标题、描述等是否相匹配来进行排名&…

福州府108m²3室2厅轻奢有度,高级耐看。福州中宅装饰,福州装修

空间之间的空间 比空间本身更具有意味&#xff0c; 但也容易被忽略&#xff0c; 正是由于“之间”的多元性和复杂性 以及它的不确定性&#xff0c; 空间之间变得无限可能。 项目信息 项目名称 | 福州府 设计地址 | 福建福州 项目面积 | 108㎡ 项目户型 | 3室2厅 设计…

安装显卡驱动、安装cuda toolkit、安装cudnn

nvidia-smi查看&#xff0c;CUDA可以向下兼容&#xff0c;以我为例&#xff0c;可以安装12.0以下的版本&#xff1a; cuda toolkit https://developer.nvidia.com/cuda-toolkit-archive 如果 你前面没有安装vs&#xff0c;直接安装的这个&#xff0c;需要把CUDA里面的 Visua…

python入门:分支结构

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 1.内容导图 2.流程图介绍 绘制要求&#xff1a;不能出现程序语言的语法 3.百分制转五级计分制 分支结构&#xff1a;语句块&#xff0c;冒号缩进表示归属 单分支…

[C++ 从入门到精通] 12.拷贝构造函数

&#x1f4e2;博客主页&#xff1a;https://loewen.blog.csdn.net&#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;本文由 丶布布原创&#xff0c;首发于 CSDN&#xff0c;转载注明出处&#x1f649;&#x1f4e2;现…

只有开源才能拯救AI

导语 | 随着 AI 技术的蓬勃发展&#xff0c;大模型的开源化正成为人工智能领域的新潮流&#xff0c;但同时引发的伦理和安全风险也饱受大家关注&#xff0c;如何把握平衡其中的尺度成为开源的一大难题。我们又应该如何有效进行开源治理&#xff1f;未来将走向何方&#xff1f;今…

1003:两个整数的四则运算

题目描述&#xff1a;输入两个整数num1和num2&#xff0c;请你设计一个程序&#xff0c;计算并输出它们的和、差、积、整数商及余数。 输入&#xff1a;输入只有两个正整数num1、num2。 输出&#xff1a;输出占一行&#xff0c;包括两个数的和、差、积、商及余数&#xff0c;数…

linux openlab搭建web网站

网站需求&#xff1a; 1.基于域名 www.openlab.com 可以访问网站内容为 welcome to openlab!!! 2.给该公司创建三个子界面分别显示学生信息&#xff0c;教学资料和缴费网站&#xff0c; 1、基于 www.openlab.com/student 网站访问学生信息&#xff0c; 2、基于 www.openlab…

个推「数据驱动运营增长」上海专场:携程智行火车票分享OTA行业的智能用户运营实践

近日&#xff0c;以“数据增能&#xff0c;高效提升用户运营价值”为主题的个推「数据驱动运营增长」城市巡回沙龙上海专场圆满举行。携程智行火车票用户运营负责人王银笛分享OTA行业的智能用户运营实践。 ▲ 王银笛 携程智行火车票用户运营负责人 负责智行业务线用户运营。从0…

【CANN】SPI通信、I2C通信

文章目录 一、SPI通信1.SPI通信2.SPI通信原理3.CPOL时钟极性、CPHA时钟相位 二、I2C通信1、I2C通信2、I2C通信原理2.1、I2C的起始和结束条件2.2、数据传送格式 总结 一、SPI通信 1.SPI通信 SPI是英语Serial Peripheral interface的缩写&#xff0c;顾名思义就是串行外围设备接…

PLM/ERP/APS/MES/SRM/CRM/WMS/QMS

参考一 ERP 1 什么是ERP ERP的英文全称是“Enterprise Resource Planning”&#xff0c;从字面上看&#xff0c;它的意思就是“企业资源计划”。ERP最开始是由美国著名的计算机技术咨询和评估集团Garter Group提出的一整套企业管理系统体系标准。 2 ERP的发展历程&#xff08…

javaEE进阶

Cookie 是可以伪造的,比如说学生证是可以伪造的 Session 是不可以伪造的,这是学校系统记录在册的 如何获取 Cookie 我们先用 Servlet 原生的获取 cookie 的方式 我们在浏览器进行访问 但是实际上目前是没有 cookie 的,我们按 F12 进行添加 然后再重新访问,就能在 idea 看到 …

冒泡排序算法原理和代码实现,就是这么简单!

冒泡排序&#xff0c;是比较简单的一种排序算法。 它的命名源于它的算法原理&#xff1a;重复的从前往后&#xff08;或者从后往前&#xff09;&#xff0c;依次比较记录中相邻的两个元素&#xff0c;如果他们顺序错误就把它们交换过来&#xff0c;直到没有再需要交换的元素&am…

虚拟人高清视频渲染宝藏工具:RenderHare飞兔渲染软件

在数字时代&#xff0c;品牌为了抢占年轻人群体&#xff0c;纷纷涌入虚拟人IP赛道&#xff0c;通过虚拟人IP运营模式&#xff0c;构建独特的虚拟人IP记忆符号&#xff0c;向粉丝输出品牌潮流、年轻化的价值观&#xff0c;扩散虚拟IP影响力&#xff0c;让品牌真正与消费者玩在一…

基于注解的声明式事务

1.什么是事务 数据库事务(transaction)是访问并可能操作各种数据项的一个数据库操作序列&#xff0c;这些操作要么全部执行要么全部不执行&#xff0c;是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。 2.事务的特性 A&#xff1a;原子性(A…