手撕链表OJ

𝙉𝙞𝙘𝙚!!👏🏻‧✧̣̥̇‧✦👏🏻‧✧̣̥̇‧✦ 👏🏻‧✧̣̥̇:Solitary-walk

      ⸝⋆   ━━━┓
     - 个性标签 - :来于“云”的“羽球人”。 Talk is cheap. Show me the code
┗━━━━━━━  ➴ ⷯ

本人座右铭 :   欲达高峰,必忍其痛;欲戴王冠,必承其重。

👑💎💎👑💎💎👑 
💎💎💎自💎💎💎
💎💎💎信💎💎💎
👑💎💎 💎💎👑    希望在看完我的此篇博客后可以对你有帮助哟

👑👑💎💎💎👑👑   
👑👑👑💎👑👑👑


目录:
一 ​​​​​​移除链表元素
二:反转一个单链表
三:链表的中间结点
四:链表中倒数第k个结点
五:合并两个有序链表
六:链表分割
七:链表的回文结构
八:相交链表

题目:

九: 环形链表
十:环形链表 II

 十一:


 1: ​​​​​​移除链表元素

思路分析 

这里咱有2中方法可以实现:

方法1:直接在原链表进行删除

总的方向:把等于val 的对应节点直接删除即可,定义三个指针:pre(当前指针的前一个节点),del(要删除的节点),cur(当前节点)

注意细节:

1)当链表第一个节点就需要删除 也就是说  pre == NULL,这时候头结点需要更新

2)正常情况的删除:改变pre指向节点的next ,这时候需要找到删除cur这个节点的前一个节点也就是pre

3非头结点并且也不需要删除:pre依次改变   即 pre = cur

对应草图如下:

OJ代码
struct ListNode* removeElements(struct ListNode* head, int val)
 {
    struct ListNode* cur = head,*pre = NULL,*del = NULL;
    while(cur)
    {
        if(cur->val == val)
        {
            if(pre == NULL)//头结点的删除
            {
                del = cur;
                cur = del->next;
              head = cur;//更新头结点
                free(del);
            }
            else
            {
                del= cur;
                cur = del->next;
                pre->next = cur;
                free(del);
        
            }
            
        }
        else
        {
            //不需删除
            pre = cur;
            cur = cur->next;

        }
    }
    return head;
}

方法2:借助链表尾插函数的思想,把不为 val对应的节点取下来进行尾插

那么问题来了:每次尾插之前都需要先找尾,在时间上就很不占优势n个节点那么对应时间复杂度就是 O(N^2) 

这里我们就需要定义一个tail指针,以此解决此问题

总的方向:不是val的节点拿下来尾插,定义三个指针  tail(尾指针) newhead(新的头结点)cur(指向原链表的当前节点)

注意细节:

1)第一个节点不为val :执行逻辑是赋值  newhead =tail =  cur; cur = cur->next;  tail->next = NULL;

2) 接下来就是尾插的逻辑,只需要更新尾结点即可  tail ->next = cur; tail = tail->next; cur = cur->next; tail->next = NULL;(注意这2句代码顺序不能颠倒) 

草图见下:

OJ完整代码:
struct ListNode* removeElements(struct ListNode* head, int val)
{    
 //方法2:尾插
    struct ListNode* tail = NULL,*newhead = NULL,*cur = head;
    if(head == NULL)
    return NULL;
    while(cur)
    {
        if(cur->val != val )
        {
            if(newhead == NULL)  //第一次尾插
            {
                newhead = tail =  cur;
                cur = cur->next;
                tail->next = NULL;
            }
            else
            {
                tail->next = cur;
                tail = tail->next;//尾结点更新
                cur = cur->next;
                tail->next = NULL;//注意以上2句代码位置不能颠倒
            }
        }
        else
        {
            struct ListNode* del  = cur;
            cur = cur->next;
            free(del);
        }
    }
    return newhead;
}

2:反转一个单链表

题目:

 思路分析

对于这题,咱也就是说,不仅仅局限于一种思维,咱格局打开 

方法1:三指针玩法(说白了,就是改变指针走向的问题)

总的方向:定义三个指针 n1 = NULL ; n2 = head; n3 = head->next ;

注意细节:

1)当链表为空的时候 

n3 = head->next; 这不就出现野指针问题了吗

合理的操作应该是:

if(head == NULL)

    return NULL;

2)循环结束条件的判断: 

3)新的头结点的返回

草图见下:

 OJ代码:
struct ListNode* reverseList(struct ListNode* head) {
    // struct ListNode* n1= NULL,*n2 = head,n3 = n2->next;//可能只有一个节点,此时n3是野指针
struct ListNode* n1= NULL,*n2 = head ;
if(head == NULL)//没有节点
return NULL;
if(head->next == NULL) //只有一个节点
return head;
    struct ListNode*n3 = n2->next;

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

 方法2:利用头插的思想,定义2个指针  newhead = NULL,cur = head;

struct ListNode* reverseList(struct ListNode* head) {

struct ListNode*  newhead = NULL,*cur = head;
if(head == NULL)
return NULL;
while(cur)
{
    struct ListNode * Next = cur->next;//保留cur的下一个节点,避免找不到
    cur->next = newhead;
    newhead = cur;//新的头结点
     cur = Next;
}
return newhead;
}
3:链表的中间结点

 思路分析

 采用快慢指针(fas指针走2步,slow指针走1步)

原理:在速度上fast永远是slow的2倍,所以当fast走到头的时候slow刚好走到链表的一半,slow所指向的节点就是链表的中间节点

 OJ代码:
struct ListNode* middleNode(struct ListNode* head) 
{
    if(head == NULL)
    return NULL;
    struct ListNode* fast = head,*slow = head;
    while(fast && fast->next)//逻辑必须是且的关系
    {
        fast = fast->next->next;
        slow = slow->next;
    }
    return slow;
}
4:链表中倒数第k个结点

题目:

思路讲解: 

方法1:快慢指针(注意这个与上面又有区别只不过思想是一致的) 

1)定义2个指针 fast,slow

2)先让fast指针走k步:利用循环来实现

3)再让2个指针一起走:fast走1步,slow走1步

fast = fast->next->next;

slow = slow->next; 

OJ代码:
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
    // write code here
    struct ListNode* fast = pListHead,*slow = pListHead,*cur = pListHead;
    if(pListHead ==NULL)
    return NULL;
    int count = 0;
    while(cur)//先求出链表长度
    {
        count++;
        cur = cur->next;
    }
    if(k > count || k == 0)
    return NULL;
    while(k--)
    {
        fast = fast->next; 
    }

    while(fast)
    {
        fast = fast->next;
        slow = slow->next;
    }
    return slow;
}
5:合并两个有序链表

题目:

思路分析: 

比较val ,取小的进行尾插

1:定义一个head 指针,一个tail 指针(免去了每一次尾插都需要找尾结点)

2:注意临界条件的判断

草图见下:

OJ代码:
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    
    struct ListNode* head = NULL,*tail = NULL;
    if( list1 == NULL&& list2 == NULL)
    return NULL;
    if(list1 == NULL)
    return list2;
    if(list2 == NULL)
    return list1;
    while(list1 && list2 )
    {
        if(list1->val >= list2->val) 
        {
            if(tail == NULL) //第一次尾插
            {
             head = tail= list2;
             list2 = list2->next;
             tail->next = NULL;
            }
            else
            {
             tail->next = list2;
             tail = tail->next;
             if(list2)
              list2 = list2->next;
             tail->next = NULL;//尾结点更新
                
            }
        }
        else
        {
             if(tail == NULL) //第一次尾插
            {
             head = tail= list1;
             list1 = list1->next;
             tail->next = NULL;
            }
            else
            {
            tail->next = list1;
             tail = tail->next;
             if(list1)
            list1 = list1->next;
             tail->next = NULL;//尾结点更新 
            }
        }
    }
    if(list1 != NULL)
    {
        tail->next = list1;
    }
    if(list2 != NULL)
    {
        tail->next = list2;

    }
    return head;
}
6:链表分割

题目:

 思路分析

首先定义2个哨兵位 : smallHead (指向小于 x值的对应链表)  bigHead(指向大于 x值的对应链表) 避免了空指针的问题

同时方便我们尾插进来找尾结点 定义2个尾指针 smallTail   bigTail

小于 x 进行尾插在 smallTail 

大于 x进行尾插在bigTail

最后把 2个链表进行连接

 草图见下

OJ代码
class Partition {
public:
ListNode* partition(struct ListNode* pHead, int x)
{
    // write code here
    /*
    思路:这两个链表一定要带哨兵位
    小于 x 的尾插到 一个链表
    大于等于 X 的尾插到另一个链表上
    对尾插的节点进行连接
     */
    struct ListNode* smallHead = nullptr, * smallTail = nullptr, * bigHead = nullptr, * bigTail = nullptr;//定义2个哨兵位
    struct ListNode* cur = pHead;
    smallHead = (struct ListNode*)malloc(sizeof(struct ListNode));
    bigHead = (struct ListNode*)malloc(sizeof(struct ListNode));
    smallHead->next = nullptr;
    smallHead->val = -1;
    bigHead->val = -1;
    bigHead->next = nullptr;

    while (cur)
    {
        if (cur->val < x)
        {
            if (smallTail == nullptr)
            {
                smallTail = cur;
                cur = cur->next;

                smallTail->next = nullptr;
                smallHead->next = smallTail;
            }
            else
            {
                smallTail->next = cur;
                cur = cur->next;

                smallTail = smallTail->next;
                smallTail->next = nullptr;
                // cur = cur->next;

            }
        }
        else
        {
            if (bigTail == nullptr)
            {
                bigTail = cur;
                cur = cur->next; NULL;
                bigHead->next = bigTail;
            }
            else
            {
                bigTail->next = cur;
                cur = cur->next;

                bigTail = bigTail->next;
                bigTail->next = nullptr;

            }
        }
    }
    //小的链表尾连接到大的链表的头
    if (smallTail)
    {
        smallTail->next = bigHead->next;

        pHead = smallHead->next;
    }
    else
    {
        pHead = bigHead->next;//smallTail可能为空
    }
    //把2个哨兵位释放

    free(smallHead);
    free(bigHead);

    return pHead;
}
};
7:链表的回文结构

题目:

思路分析:

大方向: 中间节点 + 链表逆置

1:先找到链表的中间节点 

注意:链表有偶数个节点返回第二个节点

1-> 2-> 2-> 1  对应的中间节点:就是倒数倒数第二个节点

1-> 2-> 3        对应中间节点:就是第二个节点

对于这个代码逻辑的分析,就借助题目3实现即可

链表逆置代码逻辑的分析见题目2

说实话,有的时候 "CV" 大法对于我们程序员来说还是挺香滴

有时候在修修改改,就OK

OJ代码:

class PalindromeList {
public:
struct ListNode* middleNode(struct ListNode* head) //返回链表中间节点
{
    if(head == nullptr)
    return nullptr;
    struct ListNode* fast = head,*slow = head;
    while(fast && fast->next)//逻辑必须是且的关系
    {
        fast = fast->next->next;
        slow = slow->next;
    }
    return slow;
}
struct ListNode* reverseList(struct ListNode* head) //链表逆置
{

struct ListNode*  newhead = nullptr,*cur = head;
if(head == nullptr)
return nullptr;
while(cur)
{
    struct ListNode * Next = cur->next;//保留cur的下一个节点,避免找不到
    cur->next = newhead;
    newhead = cur;//新的头结点
     cur = Next;
}
return newhead;
}
    bool chkPalindrome(ListNode* head) {
        // write code here
        // 找到中间节点(偶数个节点:返回第二个);从中间节点开始进行逆置;以此判断val
       struct ListNode * mid =  middleNode( head);
       struct ListNode * re_mid = reverseList(head);
       while(head)
       {
        if(head->val != re_mid->val)
        {
            return false;
        }
        else {
        head = head->next;
        re_mid =  re_mid->next;
        }
       }
       return true;
    }
};
8:相交链表

 题目:

对于这个OJ题,可能大部分老铁是这样想的:

对这2个链表的每个节点依次进行比较,看链表A 中的 a1是否与链表B中的某个节点相等。搞个循环就拿下了,不知道你是否思考过时间复杂度 :这个时间复杂度对应的级别O(N^2),在OJ上是跑不过去的

 思路分析:

若是2个链表的尾结点相同,岂不是就相交了

1:注意这里不能比较 节点的val是否相同(此时尾结点的val一样,但是不相交)

2:借用快慢指针的思想:定义fast (指向较长的一个链表)slow(指向链表较短的一个)

3:先让fast走绝对值步 abs(lA-lB)  :注意abs()是一个库函数

4:在让 fast  和 slow 各自走一步进行判断是否  fast == slow

5:注意一些细节处理:2个链表只有一个节点;当2个链表的长度差很大(换言之就是:slow很快就来到尾结点)

6:找链表尾结点 是 tail ->next == NULL(而不是 tail == NULL)

7:判断链表哪一个长,可以定义一个 longListNode, shortListNode,指针含义顾名思义,这样就避免了每次进循环后的重复判断

 草图见下:

 OJ代码:
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    /*
    快慢指针(拉开距离):fast(指向较长的链表)slow(指向较短链表)一起走,每次走一步,第一次 fast == slow,就是所求节点
    fast先走 差距步  abs(lA-lB)
    问题不知道那个链表是最长的,定义指针 shortList,longList
    */
    struct ListNode * tailA = headA,*tailB = headB;
   
    int lA = 0,lB = 0;
    while( tailA->next)
    {
        lA++;//注意lA最终比原链表长度少1,但并不影响 abs(lA-lB)
        tailA = tailA->next;
    }
    while(tailB->next)
    {
        lB++;
        tailB = tailB->next;
    }
    int gap = abs(lA-lB);
    if(tailB == tailA)  //相交
    {
        struct ListNode* longList= headA,*shortList = headB;//假设链表A较长
        if(lA >= lB)
        {
        longList = headA;
        shortList = headB;
        }
        else
        {
        longList = headB;
        shortList = headA;
        }
        struct ListNode*fast = longList,*slow = shortList;
        while(gap--)
        {
            fast = fast->next;
        }
        //都只有一个节点,下面循环进不去
        if(fast == slow)
        return fast;
        while(fast && fast->next)
        {
            fast = fast->next;
            if(slow != NULL)  //可能slow先来到尾结点
            slow = slow->next;
            if(fast == slow)
            return fast;
        
        }
    }
    return NULL;//不相交
}

9: 环形链表
题目:

注意此时我们找尾结点是不能解决问题的

对于这种循环链表最大的问题就是不能进行遍历,因为我们永远走不出这个圈(一直死循环) 

 思路分析:

方法:快慢指针

1:fast 和 slow 起始位置都指向头结点

2:fast 每次走 2步  fast = fast ->next ->next ;

     slow 每次走一步 slow = slow ->next ;

3: 当这2个指针相遇即代表此链表成环   即: fast == slow  ;

草图分析:

 比如说:屏幕前的老铁,这正好就是面试题之一,面试官就问原理是啥,

fast 和 slow 一定会相遇吗(fast 走2步,slow 走1步)

fast 走3 \4 \5……又可不可以呢???

 相信有不少铁子也会有疑问,为什么呀,原理是啥???

证明:

fast 每次走2步, slow 每次走一步,并且这2个指针同时从头结点开始走,那么注定fast指针先进入环,slow 指针后进入环

假设fast 指针追 slow 指针,假设fast 与slow 之间距离为 X 。在速度上 fast 是slow 是2倍,并且 2个指针又是同时从统一起始点出发的,所以当slow 第一次进入环后但没有走完第一圈,fast 肯定会追上 slow

OJ代码:
bool hasCycle(struct ListNode *head)
 {
    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if(fast == slow)
        return true;
    }
    return false;
}
10:环形链表 II

 题目:

对于这个变形题,咱先说思路,一会在进行证明 

思路分析:

方法:一个指针从头结点开始走,一个指针从相遇的节点开始走,当再次相遇即为环的入口节点(即为所求)

 1:快慢指针的思想:当 fast 和 slow 第一次相遇的时候 定义为 meet

2:有一个指针从头结点开始走,一个指针从meet 这个节点开始走,当这2个指针再次相遇即为链表成环的第一个节点

再则里,俺就偷个懒,就不画草图喽

OJ代码: 
struct ListNode *detectCycle(struct ListNode *head) 
{
    /*
    1:判断是否有环:快慢指针
    2:求入环的起始节点->假设相遇的节点是meet,让一个节点从meet开始走,一个从头结点开始走,再次相遇即为所求
    */
    struct ListNode * fast = head,*slow =  head;
    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if( slow == fast)//相遇
        {
            struct ListNode * meet = slow;
            while(meet != head)
            {
                meet = meet->next;
                head = head->next;
            }
                return meet;
            
        }
    }
    return NULL;//没有环
}

 想必有不少老铁会问,原理是啥,能对这个结论进行证明吗?

没问题,接下来3,2,1,上证明

证明:

11:随机链表的复制

题目:

分析: 

当我们看到这个链表的时候,无非就是多了一个 random 指针相较于 单链表而言

我相信有不少老铁是这样思考的:

当节点的random 指针指向非空的时候:第二个节点 直接让 random 指向 节点val 为 7的节点即可

我在这里想说是不行滴当链表LI有2个为7的节点呢,你知道先连哪一个吗?

 有那些铁子说:不如记录一下当前 random 指针指向第几个节点

这样也不是不可以的,但是效率肯定是不太好的 O(N^2)

 我这里有个最优解(仅限于使用C语言)仔细看哟,不要分心,一不小心就出差错了

额外说一下:此时对应时间复杂度的级别是 O(N)

思路分析:

首先:对原来链表进行拷贝,让原节点与拷贝节点建立联系:拷贝的节点尾插到对应节点的后面

其次:控制拷贝节点的random   注意这是解这题的核心

     当random 不为空:  copy -> random = cur ->random->next ;

     当random 为空:copy ->random = NULL ;

最后:让拷贝链表与原链表分开,同时恢复原来链表

定义 3个指针:

copyHead (拷贝链表新的头结点)  copyTail(拷贝链表的尾结点)    curNext

1)把拷贝节点拿下来尾插

对拷贝节点第一次尾插

            copyHead = copyTail = cur -> next ;

            curNext = cur->next->next;

            cur->next = curNext;//恢复原来链表

            cur = curNext;

            copyTail ->next = NULL;

之后对拷贝节点尾插逻辑:

            copyTail->next =cur->next;

            curNext = cur->next->next;

            cur ->next = curNext;//恢复原来链表

            cur = curNext;//迭代

            copyTail = copyTail->next;//尾结点及时更新

            copyTail ->next = NULL;//尾结点及时置空

2)原链表的恢复:让cur -> next = curNext ;

 

 OJ代码:
struct Node* copyRandomList(struct Node* head)
 {
     /*
     1:拷贝节点到原来节点的后面:是源节点与拷贝节点建立联系(实际上:没有任何关系:malloc)
     2:控制拷贝节点的random
     3:让拷贝节点与源节点断开 && 恢复原来链表
     */
	struct Node* cur = head,*copy = NULL;
    while(cur) //1
    {
        copy = (struct Node*)malloc(sizeof(struct Node));
        if(copy == NULL)
        return NULL;
        //开辟成功,赋值
        copy->val = cur->val;
        copy->next = cur->next;
        struct Node* curNext = cur->next;
        //插入到当前节点后面
        cur->next = copy;
        copy->next = curNext;
        cur = curNext;//迭代
    }
    cur = head;//cur重新赋值
    // copy = cur->next;
    while(cur)//2
    {
         copy = cur->next;//拷贝节点永远在cur 的后面
        if(cur->random == NULL)
        {
             copy->random = NULL;
        }
        else
        {
        copy->random = cur->random->next;
        }
        cur = copy->next;//迭代
    }
    cur = head;//cur重新赋值
    struct Node* copyHead = NULL,*copyTail = NULL,*curNext = NULL;
    while(cur)//3:把拷贝节点取下来尾插
    {
        if(copyTail ==NULL)
        {
            copyHead = copyTail = cur->next;
            curNext = cur->next->next;
            cur->next = curNext;//恢复原来链表
            cur = curNext;
            copyTail ->next = NULL;
        }
        else
        {
            copyTail->next =cur->next;
            curNext = cur->next->next;
            cur ->next = curNext;//恢复原来链表
            cur = curNext;//迭代
            copyTail = copyTail->next;//尾结点及时更新
            copyTail ->next = NULL;//尾结点及时置空
        }

    }
    return copyHead;
}
总结: 

对于我这种小白来讲,做链表方面的OJ题,结合画图来说确实是省了不少事情,相比较自己 盲想省去了不少麻烦,在之后就是自己还是要多多练习,注意指针走向,边界的判断

结语:

对于链表这块,需要咱们多多实践,这样才能知不足,而奋进。对于这个快慢指针的应用我们方向是很灵活的,有时候看似题目很难(比如求环形链表入口的第一个节点),采用快慢指针代码量瞬间就变得很精简。其次就是我们在敲代码的时候要注意“数码结合”,画图真的帮我们省了不少问题,ok,话不多说,咱走起,你是懂滴,铁子!

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

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

相关文章

揭秘 2024 春晚刘谦魔术——代码还原

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、魔术大概流程 二、代码实现各个步骤 2.1 partition&#xff08;对半撕牌&#xff09; 2.2 bottom&#xff08;将 n 张牌置底…

【Linux】环境变量及相关指令

一、环境变量的基本概念 其实&#xff0c;我们早就听说过环境变量&#xff0c;比如在学习 JAVA / Python 的时候&#xff0c;会在 Windows 上配置环境变量&#xff1a; 环境变量到底是什么呢&#xff1f; 环境变量&#xff08;environment variables&#xff09;一般是指在操作…

C++ //练习 7.3 修改7.1.1节(第229页)的交易处理程序,令其使用这些成员。

C Primer&#xff08;第5版&#xff09; 练习 7.3 练习 7.3 修改7.1.1节&#xff08;第229页&#xff09;的交易处理程序&#xff0c;令其使用这些成员。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 /********************…

CCF编程能力等级认证GESP—C++2级—20231209

CCF编程能力等级认证GESP—C2级—20231209 单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09;判断题&#xff08;每题 2 分&#xff0c;共 20 分&#xff09;编程题 (每题 25 分&#xff0c;共 50 分)小杨做题小杨的 H 字矩阵 参考答案单选题判断题编程题1编程题2 …

【Apache Superset】从概述、安装到运用,一篇掌握!

文章目录 什么是 Superset&#xff1f;Superset 的优势安装安装 Anaconda 包管理工具创建 Superset 的 Python 环境 下载 Superset 依赖更新工具安装 Superset配置 MySQL 元数据库初始化 Superset 数据库报错一报错二报错三数据库初始化完成 初始化 Superset报错一警告信息 启动…

【解决(几乎)任何机器学习问题】:超参数优化篇(超详细)

这篇文章相当长&#xff0c;您可以添加至收藏夹&#xff0c;以便在后续有空时候悠闲地阅读。 有了优秀的模型&#xff0c;就有了优化超参数以获得最佳得分模型的难题。那么&#xff0c;什么是超参数优化呢&#xff1f;假设您的机器学习项⽬有⼀个简单的流程。有⼀个数据集&…

【算法设计与分析】反转链表 ||

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;算法分析与设计 ⛺️稳中求进&#xff0c;晒太阳 题目 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表…

【MySQL】外键约束的删除和更新总结

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-7niJLSFaPo0wso60 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

【Linux 02】权限基本概念

文章目录 &#x1f308; Ⅰ 权限概念&#x1f308; Ⅱ 权限管理1. 文件访问者分类 (角色)2. 文件类型和访问权限 (事物属性)3. 文件权限值表示方法 &#x1f308; Ⅲ 权限修改1. chmod 设置文件访问权限2. chown 修改文件拥有者3. chgrp 修改文件或目录的所属组 &#x1f308; …

Hive——企业调优经验

前言 本篇文章主要整理hive-3.1.2版本的企业调优经验&#xff0c;有误请指出~ 一、性能评估和优化 1.1 Explain查询计划 使用explain命令可以分析查询计划&#xff0c;查看计划中的资源消耗情况&#xff0c;定位潜在的性能问题&#xff0c;并进行相应的优化。 explain执行计划…

LabVIEW荧光显微镜下微管运动仿真系统开发

LabVIEW荧光显微镜下微管运动仿真系统开发 在生物医学研究中&#xff0c;对微管运动的观察和分析至关重要。介绍了一个基于LabVIEW的仿真系统&#xff0c;模拟荧光显微镜下微管的运动过程。该系统提供了一个高效、可靠的工具&#xff0c;用于研究微管与运动蛋白&#xff08;如…

汉诺塔问题——递归算法与非递归算法

一、问题描述 汉诺塔问题是一个经典的问题。汉诺塔&#xff08;Hanoi Tower&#xff09;&#xff0c;又称河内塔&#xff0c;源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子&#xff0c;在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令…

Spring 用法学习总结(一)之基于 XML 注入属性

百度网盘&#xff1a; &#x1f449; Spring学习书籍链接 Spring学习 1 Spring框架概述2 Spring容器3 基于XML方式创建对象4 基于XML方式注入属性4.1 通过set方法注入属性4.2 通过构造器注入属性4.3 使用p命名空间注入属性4.4 注入bean与自动装配4.5 注入集合4.6 注入外部属性…

auto.js教程(autojs教程、autox.js、autoxjs)笔记(二)环境搭建——2、安卓手机投屏软件scrcpy的安装和使用(scrcpy教程)

参考文章&#xff1a;【自动化技术】Autojs从入门到精通 参考文章&#xff1a;AutoXJS开发入门简介菜鸟教程 参考文章&#xff1a;关于Auto.js的下架说明 参考文章&#xff1a;Auto.js 4.1.0 文档 文章目录 005--【环境搭建】2、安卓手机投屏软件scrcpy的安装和使用scrcpy官…

【1024】我的创作纪念日

机缘 1024天了&#xff0c;开始在这里学习编程知识、IT技能&#xff0c;CSDN让我发现了一群热爱学习和分享的小伙伴&#xff0c;也逐渐在这里稳定下来。 收获 不知不觉已经两年多过去了&#xff0c;通过不断的分享&#xff0c;不仅自己的知识技能得到了提升&#xff0c;能帮…

腾讯云4核8G服务器多少钱?

腾讯云4核8G服务器多少钱&#xff1f;轻量应用服务器4核8G12M带宽一年446元、646元15个月&#xff0c;云服务器CVM标准型S5实例4核8G配置价格15个月1437.3元&#xff0c;5年6490.44元&#xff0c;标准型SA2服务器1444.8元一年&#xff0c;在txy.wiki可以查询详细配置和精准报价…

SpringCloud-Hystrix:服务熔断与服务降级

8. Hystrix&#xff1a;服务熔断 分布式系统面临的问题 复杂分布式体系结构中的应用程序有数十个依赖关系&#xff0c;每个依赖关系在某些时候将不可避免失败&#xff01; 8.1 服务雪崩 多个微服务之间调用的时候&#xff0c;假设微服务A调用微服务B和微服务C&#xff0c;微服…

B2科目二考试项目笔记

B2科目二考试项目笔记 1 桩考1.1 右起点倒库1.2 移库&#xff08;左→右&#xff09;1.3 驶向左起点1.4 左起点倒库1.5 驶向右起点 2 侧方停车考试阶段&#xff08;从路边开始&#xff09;&#xff1a; 3 直角转弯4 坡道定点停车和起步5 单边桥6 通过限速限宽门7 曲线行驶8 连续…

[数学建模] 计算差分方程的收敛点

[数学建模] 计算差分方程的收敛点 差分方程&#xff1a;差分方程描述的是在离散时间下系统状态之间的关系。与微分方程不同&#xff0c;差分方程处理的是在不同时间点上系统状态的变化。通常用来模拟动态系统&#xff0c;如在离散时间点上更新状态并预测未来状态。 收敛点&…

Selenium图表自动化开篇

目录 前言&#xff1a; 使用 Canvas 或者 SVG 渲染 选择哪种渲染器 代码触发 ECharts 中组件的行为 前言&#xff1a; 图表自动化一直以来是自动化测试中的痛点&#xff0c;也是难点&#xff0c;痛点在于目前越来越多公司开始构建自己的BI报表平台但是没有合适的自动化测试…