【数据结构练习题】单链表问题解决(虚拟头节点法,递归,快慢指针法)

目录

  • 1.删除单链表中的元素
    • 1.1 删除排序链表中的重复元素
    • 1.2 删除排序链表中的重复元素Ⅱ
    • 1.3 移除链表元素
  • 2.反转链表
    • 2.1 反转链表
    • 2.2 反转链表Ⅱ
  • 3.查找链表中结点
    • 3.1 链表的中间结点
    • 3.2 链表中倒数第k个节点
  • 4.回文链表
  • 5.相交链表
  • 6.合并链表

知识补充:

递归三要素:

  1. 大问题能拆成若干个小问题的解。
  2. 拆分后的子问题和原问题除了数据规模不同,思路完全相同。
  3. 存在问题的终止条件,不借助任何外部函数的特殊值,直接得出答案。

链表问题三大常用方法:

  1. 虚拟头节点法
  2. 递归
  3. 快慢指针法

1.删除单链表中的元素

1.1 删除排序链表中的重复元素

题目链接: 83.删除链表中的重复元素


题目内容:给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次返回已排序的链表 。

示例
在这里插入图片描述
输入:head = [1,1,2,3,3]
输出:[1,2,3]


解法1:迭代

要找重复元素,这里使用两个引用:prev,cur

  1. base case:若链表为空或只有一个元素,肯定不会有重复元素,直接返回即可。
  2. 当链表长度大于1时,给定一个虚拟头结点,让prev指向虚拟头结点,cur指向后一个节点。判断这两个节点的值是否相同。
  3. 若不相同,则prev=prev.next。
  4. 若相同,prev.next=cur.next,使prev指向相同元素节点的下一个节点,cur=cur.next,再继续判断,重复以上过程。
  5. 最后返回dummyHead.next即可。

在这里插入图片描述

    public ListNode deleteDuplicates(ListNode head) {
        //base case
        if(head==null || head.next==null){
            return head;
        }
        //此时链表一定两个节点
        //虚拟头节点
        ListNode dummyhead=new ListNode(-101);
        dummyhead.next=head;
        //prev指向的一定不是重复元素
        ListNode prev=dummyhead;
        //双指针比较元素是否重复
        ListNode cur=prev.next;
        while(cur!=null){
            if(prev.val==cur.val){
                prev.next=cur.next;
            }else{
                prev=prev.next;
            }
            cur=cur.next;
        }
        return dummyhead.next;
    }

解法2:递归

链表是天然的递归结构。

首先,明确deleteDuplicates()方法的作用是删除所有重复的元素,得到一个所有元素只出现一次的已排序的链表 。

那么,整个链表就可以分为 head+除head以外的所有节点
在这里插入图片描述
head+deleteDuplicates(head.next)
此时deleteDuplicates(head.next)已经是一个没有重复元素的链表,那么只需要判断head和此链表的head的值是否相同。

步骤:

  1. 边界条件,若链表为空或只有一个元素,肯定不会有重复元素,直接返回即可。
  2. 要删除重复元素,先把以head.next为头结点的子链表中的所有重复元素删除完。
  3. 最后比较head和head.next的值。
    public ListNode deleteDuplicates(ListNode head) {
        //base case
        if(head==null || head.next==null){
            return head;
        }
        head.next=deleteDuplicates(head.next);
        return head.val==head.next.val ? head.next:head;
    }

1.2 删除排序链表中的重复元素Ⅱ

题目链接: 82.删除排序链表中的重复元素Ⅱ


题目内容: 给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。

示例:
在这里插入图片描述
输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]

本题和上一题不同的地方在于,只留下不同的元素,重复元素一个不留。


解法1:迭代

这里使用三指针法:prev,cur,sec

  • prev一定指向不同元素
  • sec一定指定cur的下一个

在这里插入图片描述

步骤:

  1. 边界条件,若链表为空或只有一个元素,肯定不会有重复元素,直接返回即可。
  2. sec==null时,循环结束,没有可比较的对象了。
  3. cur.val != sec.valprev=prev.next,prev向后移动。
  4. cur.val==sec.val时,循环判断,sec一直向后移动,直到cur.val != sec.val,此时prev.next指向sec。
  5. cur移动到sec的位置。在新一轮循环中,让sec=cur.next。继续判断。
public ListNode deleteDuplicates(ListNode head) {
        //base case
        if(head==null || head.next==null){
            return head;
        }
        //虚拟头结点
        ListNode dummyHead=new ListNode(-101);
        dummyHead.next=head;
        ListNode prev=dummyHead;
        ListNode cur=prev.next;
        while(cur!=null){
            ListNode sec=cur.next;
            if(sec==null){
                break;
            }
            if(cur.val!=sec.val){
                prev=prev.next;
            }else{
                while( sec!=null && cur.val==sec.val){
                    sec=sec.next;
                }
                //此时,sec和cur一定不相等
                prev.next=sec;
            }
            cur=sec;
        }
        return dummyHead.next;
    }

解法2:递归

链表可以看作head以head.next为头结点的子链表的组合。
在这里插入图片描述

思路:

  1. 边界条件,若链表为空或只有一个元素,肯定不会有重复元素,直接返回即可。
  2. head.val !=head.next.val,head.next直接指向以head.next为头结点的链表。
  3. head.val ==head.next.val,此时头结点就是重复的节点,先处理头结点的情况,给定一个引用newHead等于head.next。判断head.val==newHead.val,若相等,让newHead不停向后移动,直到不相等。此时newHead一定不是重复元素,返回deleteDuplicates(newHead)
    public ListNode deleteDuplicates(ListNode head) {
        //base case
        if(head==null || head.next==null){
            return head;
        }
        if(head.val !=head.next.val){
            head.next=deleteDuplicates(head.next);
            return head;
        }else{
        	//头结点就是重复的节点,先处理完头结点的情况
            ListNode newHead=head.next;
            while(newHead!=null && head.val==newHead.val){
                newHead=newHead.next;
            }
            //此时newHead一定不是重复元素
            return(deleteDuplicates(newHead));
        }
    }

1.3 移除链表元素

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


题目内容: 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

示例:
在这里插入图片描述
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]


解法1:迭代

思路:

  1. 边界条件,如何head为空,直接返回null。
  2. 给定一个虚拟头结点,连接head。给定一个引用prev指向虚拟头结点。(注意:prev一定指向值不为val的节点)
  3. 遍历链表。若prev.next.val==val,prev直接指向prev.next的下一个节点。
  4. 若不相等,prev直接向后移动。
		public ListNode removeElements(ListNode head, int val) {
        //1.base case
        if(head==null){
            return null;
        }
        //虚拟头节点
        ListNode dummyHead=new ListNode();
        dummyHead.next=head;
        //prev一定指向值不为val的节点
        ListNode prev=dummyHead;
        while(prev.next!=null){
            if(prev.next.val==val){
                prev.next=prev.next.next;
            }else{
                prev=prev.next;
            }
        }
        return dummyHead.next;
    }

解法2:递归

链表可以看作head以head.next为头结点的子链表的组合。
在这里插入图片描述

思路:

  1. 边界条件,如何head为空,直接返回null。
  2. removeElements(head.next,val)一定是值不为val的链表。head.next直接指向removeElements(head.next,val)
  3. 此时只需判断头节点的值是否为val。若是,返回head.next,否则返回head。
    public ListNode removeElements(ListNode head, int val) {
        //base case
        if(head==null){
            return null;
        }
        head.next=removeElements(head.next,val);
        return head.val==val ? head.next:head;
    }

2.反转链表

2.1 反转链表

题目链接:206.反转链表


题目内容: 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例:
在这里插入图片描述
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]


解法1:头插法

思路:若题目没有空间限制,则可以遍历原链表,不断产生新节点,在头插到新链表中,最后返回新链表。

   public ListNode reverseList(ListNode head) {
        //base case 
        if(head==null || head.next==null){
            return head;
        }
        //虚拟头结点
        ListNode dummyHead=new ListNode(-1);
        //不断遍历原链表,产生新节点,头插到新链表
        while(head!=null){
            ListNode cur=new ListNode(head.val);
            cur.next=dummyHead.next;
            dummyHead.next=cur;
            head=head.next;
        }
        return dummyHead.next;
    }

解法2:原地反转

思路:

  1. 原先prev是指向cur的,反过来,让cur指向prev就实现了反转。
  2. 但是cur.next指向prev之后,剩下的链表就断开了找不到了,所以需要先用一个next记住原链表cur的下一个节点。
    当cur为null时,prev刚好在最后一个节点,直接返回prev即可。

在这里插入图片描述

    public ListNode reverseList(ListNode head) {
        //base case
        if(head==null || head.next==null){
            return null;
        }
        ListNode prev=null;
        ListNode cur=head;
        while(cur!=null){
            ListNode next=cur.next;
            cur.next=prev;
            prev=cur;
            cur=next;
        }
        return prev;
    }

解法3:递归

思路:

  1. reverseList(ListNode head)的作用是得到一个反转后的链表。

  2. 则可以把链表分为头节点和以head.next为头节点的反转后的链表。

  3. 此时只需要将head连接到子链表的尾端即可。

在这里插入图片描述

    public ListNode reverseList(ListNode head) {
        if(head==null || head.next==null){
            return head;
        }
        ListNode next=head.next;
        ListNode newHead=reverseList(head.next);
        //拼接当前头节点和转后的子链表
        head.next=null;
        next.next=head;
        return newHead;
    }

2.2 反转链表Ⅱ

题目链接:92.反转链表Ⅱ

解法:

思路:

  1. 给定两个引用,记住left的前一个节点和right的后一个节点。
  2. 先将待反转的区域反转
  3. 把 pre 的 next 指针指向反转以后的链表头节点,把反转以后的链表的尾节点的 next 指针指向 succ。

在这里插入图片描述

    public ListNode reverseBetween(ListNode head, int left, int right) {
        //base case
        if(head==null || head.next==null){
            return head;
        }
        ListNode dummyHead=new ListNode(-1);
        dummyHead.next=head;
        
        ListNode prev=dummyHead;
        //从temp开始走,来到left的前一个节点
        for(int i=0;i<left-1;i++){
            prev=prev.next;
        }
        //从prev开始走,一直到right节点
        ListNode rightNode=prev;
        for(int i=0;i<right-left+1;i++){
            rightNode=rightNode.next;
        }
        
        //截取要反转的链表
        ListNode next=rightNode.next;
        ListNode leftNode=prev.next;
        //切断连接
        prev.next=null;
        rightNode.next=null;

        //反转链表子区间
        reverseList(leftNode);

        //接回原链表
        prev.next=rightNode;
        leftNode.next=next;
        return dummyHead.next;
    }

    public ListNode reverseList(ListNode head) {
        ListNode prev=null;
        ListNode cur=head;
        while(cur!=null){
            ListNode next=cur.next;
            cur.next=prev;
            prev=cur;
            cur=next;
        }
        return prev;
    }

3.查找链表中结点

3.1 链表的中间结点

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


题目内容: 给你单链表的头结点 head ,请你找出并返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。

示例:
在这里插入图片描述
输入:head = [1,2,3,4,5]
输出:[3,4,5]
解释:链表只有一个中间结点,值为 3 。


解法1:按长度查找

步骤:

  1. 遍历原链表,得到链表的长度
  2. 若长度为奇数,直接走 长度/2 的步数。
  3. 若长度为偶数,也是直接走 长度/2 的步数。
    public ListNode middleNode(ListNode head) {
        int count=0;
        ListNode temp=head;
        while(temp!=null){
            temp=temp.next;
            count++;
        }
        int n=count/2;
        while(n>0){
            head=head.next;
            n--;
        }
        return head;
    }

解法2:快慢指针法

思路:

  1. 两个指针,low 和 fast
  2. low每走一步,fast就走两步
  3. 当fast走到终点,low就停在我们想要的位置

在这里插入图片描述

    public ListNode middleNode(ListNode head) {
        ListNode low=head;
        ListNode fast=head;
        while(fast!=null && fast.next!=null){
            low=low.next;
            fast=fast.next.next;
        }
        return low;
    }

3.2 链表中倒数第k个节点

题目链接:剑指Offer 22.链表中倒数第k个结点


题目内容: 输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。

示例:

给定一个链表: 1->2->3->4->5, 和 k = 2.

返回链表 4->5.


解法1:按长度查找

思路:

  1. 遍历链表,得到链表的长度n。
  2. 倒数第k个结点就是正数第n-k个结点。
    public ListNode getKthFromEnd(ListNode head, int k) {
        if(head==null || k<=0){
            return null;
        }
        ListNode temp=head;
        int n=0;
        while(temp!=null){
            temp=temp.next;
            n++;
        }
        int count=n-k;
        while(count>0){
            head=head.next;
            count--;
        }
        return head;
    }

解法2:快慢指针法

思路:

  1. 给定两个引用sec,fir
  2. fir先向前走k步。
  3. sec 和 fir 同时向前走,当fir为null时,sec刚好指向倒数dik个结点。

在这里插入图片描述

    public ListNode getKthFromEnd(ListNode head, int k) {
        if(head==null || k<=0){
            return null;
        }
        ListNode fir=head;
        ListNode sec=head;
        for(int i=0;i<k;i++){
            //判断k>链表长度的情况
            if(fir==null){
                return null;
            }
            fir=fir.next;
        }
        while(fir!=null){
            fir=fir.next;
            sec=sec.next;
        }
        return sec;
    }

4.回文链表

题目链接:234.回文链表


题目内容: 给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。

示例:
在这里插入图片描述
输入:head = [1,2,2,1]
输出:true


解法

思路:

  1. 判断回文链表其实就是判断对称链表。
  2. 将链表一份为二,l1为头节点到中间结点的链表,l2为中间结点到尾节点的链表。
  3. 将l2反转,与l1的值进行对比。遍历,直到其中一条链表走到null,若有不一样的值,则不为回文链表。反之,则是回文链表。

在这里插入图片描述

   public boolean isPalindrome(ListNode head) {
        if(head==null || head.next==null){
            return true;
        }
        ListNode middleNode=middleNode(head);
        //反转中间结点之后的链表
        ListNode l2=reverseList(middleNode);
        //找反例
        while(head!=null && l2!=null){
            if(head.val != l2.val){
                return false;
            }
            head=head.next;
            l2=l2.next;
        }
        return true;
    }
    //查找中间节点
    public ListNode middleNode(ListNode head) {
        int count=0;
        ListNode temp=head;
        while(temp!=null){
            temp=temp.next;
            count++;
        }
        int n=count/2;
        while(n>0){
            head=head.next;
            n--;
        }
        return head;
    }
    //反转链表
      public ListNode reverseList(ListNode head) {
        if(head==null || head.next==null){
            return head;
        }
        ListNode next=head.next;
        ListNode newHead=reverseList(head.next);
        //拼接当前头节点和转后的子链表
        head.next=null;
        next.next=head;
        return newHead;
    }

5.相交链表

题目链接:160.相交链表


题目内容: 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。

示例:
在这里插入图片描述
输入: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 中第四个节点) 在内存中指向相同的位置。


解法:

如图所示:

  • listA的长度=x+z
  • listB的长度=y+z

但若让A和B都走一遍对方的路程:即 x+z+y=y+z+x。此时它们的路程一定相等,走完之后一定会相交。

在这里插入图片描述
过程图举例:
在这里插入图片描述

步骤:

  1. 引入两个引用listA,listB。
  2. listA走到终点后倒过来走listB。
  3. listB走到终点后倒过来走listA。
  4. 若不存在交点,则listA和listB最后都指向null。
  5. 若存在交点,则两个链表走完全程后一定指向交点。
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        //引入两个引用
        ListNode listA=headA;
        ListNode listB=headB;

        while(listA!=listB){
            listA = listA==null ? headB:listA.next;
            listB = listB==null ? headA:listB.next;
        }
        return listA;
    }

6.合并链表

题目链接:21.合并两个有序链表

题目内容: 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。


示例:
在这里插入图片描述
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]


解法1:虚拟头节点法

思路:

  1. 给定一个虚拟头结点dummyHead;
  2. 遍历两个链表。比较结点值的大小,将较小值拼接在新链表后面。

图解:

在这里插入图片描述

    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        if(list1==null){
            return list2;
        }
        if(list2==null){
            return list1;
        }
        ListNode dummyHead=new ListNode(-1);
        ListNode tail=dummyHead;
        //取较小值拼接在链表的尾部
        while(list1!=null && list2!=null){
            if(list1.val<list2.val){
                tail.next=list1;
                tail=list1;
                list1=list1.next;
            }else{
                tail.next=list2;
                tail=list2;
                list2=list2.next;
            }
        }
        //此时,至少一个链表为Null
        if(list1==null){
            tail.next=list2;
        }
        if(list2==null){
            tail.next=list1;
        }
        return dummyHead.next;
    }

解法2:递归

思路:

  1. 已知 mergeTwoLists(ListNode list1, ListNode list2)方法的作用是将两个升序链表合并为一个新的 升序 链表并返回。
  2. 如果list1.val<list2.val,此题可以看作list1+ mergeTwoLists(ListNode list1.next, ListNode list2)
  3. 如果list2.val<list1.val,此题可以看作list2+ mergeTwoLists(ListNode list1, ListNode list2.next)
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        if(list1==null){
            return list2;
        }
        if(list2==null){
            return list1;
        }
        if(list1.val<=list2.val){
            list1.next=mergeTwoLists(list1.next,list2);
            return list1;
        }else{
            list2.next=mergeTwoLists(list1,list2.next);
            return list2;
        }
    }

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

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

相关文章

【GITHUB】FlipIt – Windows的开源翻页时钟

FlipIt 是一款免费开源的翻页时钟应用&#xff0c;专为 Windows 平台设计。该应用灵感来源于备受喜爱的老牌翻页时钟应用 Fliqlo&#xff0c;后者被公认为经典的翻页时钟屏保。然而&#xff0c;由于 Fliqlo 是基于 Flash 技术开发的&#xff0c;随着微软最近正式禁用 Flash&…

非凸科技受邀参加中科大线上量化分享

7月30日&#xff0c;非凸科技受邀参加由中国科学技术大学管理学院学生会、超级量化共同组织的“打开量化私募的黑箱”线上活动&#xff0c;分享量化前沿以及求职经验&#xff0c;助力同学们拿到心仪的offer。 活动上&#xff0c;非凸科技量化策略负责人陆一洲从多个角度分享了如…

跑步用哪款耳机比较好、最适合跑步用的蓝牙耳机推荐

运动时聆听音乐可以为枯燥的过程带来娱乐&#xff0c;并且能够转移注意力&#xff0c;让人忽略身体负荷带来的不适感。而一款出色的运动耳机则成为锻炼过程中的重要辅助&#xff0c;它能够帮助控制节奏&#xff0c;使运动过程更加愉悦和高效。以下是一些备受推崇的热门运动耳机…

安卓手机录屏怎么把小白点去掉?试试这种方法

随着安卓手机功能的不断升级&#xff0c;录屏已经成为了一项基本功能。然而&#xff0c;当我们录制完视频后&#xff0c;常常会发现视频中有许多小白点&#xff0c;影响了视频的美观度。那么&#xff0c;如何去除这些小白点呢&#xff1f;本文将为大家介绍几种简单易行的方法。…

Linux系统jenkins+newman+postman持续集成环境搭建

1、首先安装nodejs 下载nodejs压缩包&#xff0c;下载地址&#xff1a;nodejs官网下载 建议不用下载最新的&#xff0c;我这里用的是推荐的v12.18版本 下载和解压命令 wget https://nodejs.org/dist/v12.18.3/node-v12.18.3-linux-x64.tar.xz解压安装包&#xff08;记得没有z&…

数据结构:插入排序

直接插入排序 插入排序算法是所有排序方法中最简单的一种算法&#xff0c;其主要的实现思想是将数据按照一定的顺序一个一个的插入到有序的表中&#xff0c;最终得到的序列就是已经排序好的数据。 直接插入排序是插入排序算法中的一种&#xff0c;采用的方法是&#xff1a;在…

规划路线(微信小程序、H5)

//地图getLocationDian(e1, e2) {console.log(e1, e2);let self this;self.xx1 [];self.xx2 [];self.points [];// self.markers[]console.log(self.markers, >marks);// self.$jsonp(url, data).then(re > {// var coors re.result.routes[0].polyline;// for (v…

leaflet-uniapp 缩放地图的同时 显示当前缩放层级

记录实现过程&#xff1a; 需求为移动端用户在使用地图时&#xff0c;缩放地图的同时&#xff0c;可以获知地图此时缩放的级别。 效果图如下&#xff1a;此时缩放地图级别为13 map.on() 有对应的诸多行为 查看官网即可&#xff0c;这里根据需要为--zoomstart zoom zoomend 代…

AWS多账户单点登录 IAM Identity Center(AWS SSO)

需求场景 多个aws账户&#xff0c;登陆麻烦且不安全&#xff0c;SSO单点功能并且外部身份提供者 — 如果您要管理外部身份提供者&#xff08;IdP&#xff09;&#xff08;例如 Okta 或 Active Directory&#xff09;中的用户。 官方文档&#xff1a;https://docs.aws.amazon.c…

【无标题】云原生在工业互联网的落地及好处!

什么是工业互联网&#xff1f; 工业互联网&#xff08;Industrial Internet&#xff09;是新一代信息通信技术与工业经济深度融合的新型基础设施、应用模式和工业生态&#xff0c;通过对人、机、物、系统等的全面连接&#xff0c;构建起覆盖全产业链、全价值链的全新制造和服务…

1.Kubernetes

文章目录 KubernetesK8S概述作用为什么使用K8S主要功能Kubernetes 集群架构与组件总结&#xff1a; 核心组件Master组件Kube-apiserverKube-controller-managerKube-scheduler工作 配置存储中心etcd Node组件KubeletKube-Proxydocker 或 containerd 总结&#xff1a; 工作流程K…

【SpringBoot】有哪些优点+配置文件如何配置?

博主简介&#xff1a;想进大厂的打工人博主主页&#xff1a;xyk:所属专栏: JavaEE进阶 Spring 的诞⽣是为了简化 Java 程序的开发的&#xff0c;⽽ Spring Boot 的诞⽣是为了简化 Spring 程序开发 的。Spring Boot是一个开源的Java框架&#xff0c;用于快速构建应用程序和微服…

ansible常见模块的运用

ansible常见模块的运用 一&#xff1a;Ansible简介二&#xff1a;ansible 环境安装部署管理端安装 ansibleansible 目录结构配置主机清单配置密钥对验证 三&#xff1a;ansible 命令行模块1&#xff0e;command 模块在远程主机执行命令&#xff0c;不支持管道&#xff0c;重定向…

LNMP安装

目录 1、LNMP简述&#xff1a; 1.1、概述 1.2、LNMP是一个缩写词&#xff0c;及每个字母的含义 1.3、编译安装与yum安装差异 1.4、编译安装的优点 2、通过LNMP创建论坛 2.1、 安装nginx服务 2.1.1、关闭防火墙 2.1.2、创建运行用户 2.1.3、 编译安装 2.1.4、 优化路…

【C#学习笔记】引用类型(2)

文章目录 ObjectEqualsGetTypeToStringGetHashCode string逐字文本复合格式字符串字符串内插 StringBuilderStringBuilder 的工作原理StringBuilder提供的方法访问字符迭代字符查询字符 dynamic Object 支持 .NET 类层次结构中的所有类&#xff0c;并为派生类提供低级别服务。…

物理机是什么?有什么优势?可以上堡垒机吗?

你知道物理机是什么&#xff1f;有什么优势&#xff1f;可以上堡垒机吗&#xff1f;今天我们就来简单聊聊。 物理机是什么&#xff1f; 物理机是相对于虚拟机而言的对实体计算机的称呼。物理机提供给虚拟机以硬件环境&#xff0c;有时也称为“寄主”或“宿主”。 物理机有什么…

万界星空科技/免费开源MES系统/免费仓库管理

仓库管理&#xff08;仓储管理&#xff09;&#xff0c;指对仓库及仓库内部的物资进行收发、结存等有效控制和管理&#xff0c;确保仓储货物的完好无损&#xff0c;保证生产经营活动的正常进行&#xff0c;在此基础上对货物进行分类记录&#xff0c;通过报表分析展示仓库状态、…

软件设计师(六)结构化开发方法

结构化方法由结构化分析、结构化设计、结构化程序设计构成&#xff0c;它是一种面向数据流的开发方法。 分类说明结构化分析&#xff08;SA&#xff09;根据分解与抽象的原则&#xff0c;按照系统中数据处理的流程&#xff0c;用数据流图来建立系统的功能模型&#xff0c;从而…

7种有效安全的网页抓取方法,如何避免被禁止?

网页抓取是一种从互联网上抓取网页内容的过程&#xff0c;但在网络抓取种相信您也经常遇到障碍&#xff1f;尤其是做跨境业务的&#xff0c;在抓取国外的网站时更有难度。但我们站在您的立场上&#xff0c;提供七种有效的方法来进行网页抓取而不被阻止&#xff0c;最大限度地降…

python可以做哪些小工具,python可以做什么小游戏

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python可以做什么好玩的&#xff0c;python可以做什么小游戏&#xff0c;今天让我们一起来看看吧&#xff01; 最近有几个友友问我说有没有比较好玩的Python小项目来练手&#xff0c;于是我找了几个比较有意思的给他们&…