leetcode--链表

news2024/10/6 0:27:01

链表

  • 1.链表的基本操作
    • (1)反转链表(206)
    • (2) 合并两个有序链表(21)
    • (3)两两交换链表中的节点(24)
  • 2.其它链表技巧
    • (1)相交链表(160)
    • (2)回文链表(234)
  • 3.练习
    • (1)删除排序链表中的重复元素(83)
    • (2)奇偶链表(328)
    • (3)删除链表的倒数第 N 个结点
    • (4)排序链表(148)

1.链表的基本操作

(1)反转链表(206)

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

输入:head = []
输出:[]
//迭代
public class Solution {

    public static void main(String[] args) {
        ListNode listNode=new ListNode(1,new ListNode(2,new ListNode(3)));
        Solution solution=new Solution();
        ListNode list = solution.reverseList(listNode);
        while (list!=null){
            System.out.print(list.val+" ");
            list=list.next;
        }
    }

    public ListNode reverseList(ListNode head) {
        if (head==null){
            return null;
        }
        ListNode cur=head;//当前节点
        ListNode pre=null;//当前节点前一个节点 初始化为null
        while (cur!=null){//遍历整个链表
            ListNode next=cur.next;//保存下一个节点 作为下一次的当前节点
            cur.next=pre;//当前节点的下一个节点指向之前的节点 实现反转
            pre=cur;//将当前节点作为下一次的前一个节点
            cur=next;
        }
        return pre;
    }

}


//递归
public class Solution {

    public static void main(String[] args) {
        ListNode listNode=new ListNode(1,new ListNode(2,new ListNode(3)));
        Solution solution=new Solution();
        ListNode list = solution.reverseList(listNode);
        while (list!=null){
            System.out.print(list.val+" ");
            list=list.next;
        }
    }

    public ListNode reverseList(ListNode head) {
        if (head==null||head.next==null){
            return head;
        }
        ListNode newHead=reverseList(head.next);
        head.next.next=head;
        head.next=null;
        return newHead;
    }

}

(2) 合并两个有序链表(21)

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

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

输入:l1 = [], l2 = []
输出:[]

输入:l1 = [], l2 = [0]
输出:[0]
public class Solution {

    public static void main(String[] args) {
        ListNode list1=new ListNode(1,new ListNode(2,new ListNode(3)));
        ListNode list2=new ListNode(0,new ListNode(3,new ListNode(4)));
        Solution solution=new Solution();
        ListNode list = solution.mergeTwoLists(list1,list2);
        while (list!=null){
            System.out.print(list.val+" ");
            list=list.next;
        }
    }

    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode pre=new ListNode(0);//设置一个头节点
        ListNode head=pre;
        while (list1!=null&&list2!=null){
            if (list1.val<= list2.val){
                head.next=list1;
                list1=list1.next;
            }else {
                head.next=list2;
                list2=list2.next;
            }
            head=head.next;
        }
        if (list1!=null){
            head.next=list1;
        }else {
            head.next=list2;
        }
        return pre.next;
    }

}

(3)两两交换链表中的节点(24)

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

输入:head = [1,2,3,4]
输出:[2,1,4,3]

输入:head = []
输出:[]

输入:head = [1]
输出:[1]
//迭代
public class Solution {

    public static void main(String[] args) {
        ListNode list1=new ListNode(1,new ListNode(2,new ListNode(3,new ListNode(4))));
        Solution solution=new Solution();
        ListNode list = solution.swapPairs(list1);
        while (list!=null){
            System.out.print(list.val+" ");
            list=list.next;
        }
    }

    public ListNode swapPairs(ListNode head) {
        ListNode listNode=new ListNode(-1);//设置一个首部节点 首部节点的下一个节点指向head的头节点
        listNode.next=head;
        ListNode temp=listNode;//标志节点 指向当前要交换的节点的前一个结点
        //当temp后边只有一个节点或者没有节点时 交换结束
        while (temp.next!=null&&temp.next.next!=null){
            //需要交换的两个节点
            ListNode list1=temp.next;
            ListNode list2=temp.next.next;
            //交换两个节点
            temp.next=list2;//标志节点的下一个节点是list2
            list1.next=list2.next;
            list2.next=list1;
            temp=list1;//更换标志节点
        }
        return listNode.next;
    }

}

2.其它链表技巧

(1)相交链表(160)

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

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

输入: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 中第四个节点) 在内存中指向相同的位置。
//集合
public class Solution {

    public static void main(String[] args) {
        ListNode list1=new ListNode(1,new ListNode(2,new ListNode(3,new ListNode(4))));
        ListNode list2=new ListNode(3,new ListNode(2,new ListNode(3,new ListNode(4))));
        Solution solution=new Solution();
        ListNode list = solution.getIntersectionNode(list1,list2);
        while (list!=null){
            System.out.print(list.val+" ");
            list=list.next;
        }
    }

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        //设置一个节点指向headA的头节点 因为题目要求返回后链表的原始结构不变 所以设置
        ListNode tempA=headA;
        ListNode tempB=headB;
        Set<ListNode> set=new HashSet<>();//存储节点
        //将headA的所有节点加入集合
        while (tempA!=null){
            set.add(tempA);
            tempA=tempA.next;
        }
        //在headB中如果找到第一个相等的节点 那么这个节点之后的其他节点都相等 返回这个节点
        while (tempB!=null){
            if (set.contains(tempB)){
                return tempB;
            }
            tempB=tempB.next;
        }
        return null;
    }

}


//双指针
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode tempA=headA;
        ListNode tempB=headB;
        while (tempA!=tempB){
            tempA=tempA==null?headB:tempA.next;
            tempB=tempB==null?headA:tempB.next;
        }
        return tempA;
    }

(2)回文链表(234)

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

输入:head = [1,2,2,1]
输出:true

输入:head = [1,2]
输出:false
//将值复制到数组后用双指针法
public class Solution {

    public static void main(String[] args) {
        ListNode list1=new ListNode(1,new ListNode(1,new ListNode(2,new ListNode(1))));
        Solution solution=new Solution();
        System.out.println(solution.isPalindrome(list1));
    }

    public boolean isPalindrome(ListNode head) {
        ListNode cur=head;//当前节点
        List<Integer> list=new ArrayList<>();
        //遍历链表 将元素加入list集合
        while (cur!=null){
            list.add(cur.val);
            cur=cur.next;
        }
        //使用两个指针 分别从头和尾开始遍历 判断是否相等
        int left=0;
        int right=list.size()-1;
        while (left<=right){
            //如果不相等 返回false
            if (!list.get(left).equals(list.get(right))){
                return false;
            }
            left++;
            right--;
        }
        return true;
    }

}


//反转后半部分链表然后比较 链表全部反转然后和原链表比较是不可行的
//因为这样的话原链表会只存在一个头节点 后边节点会消失
public class Solution {

    public static void main(String[] args) {
        ListNode list1=new ListNode(1,new ListNode(1,new ListNode(2,new ListNode(1))));
        Solution solution=new Solution();
        System.out.println(solution.isPalindrome(list1));
    }

    public boolean isPalindrome(ListNode head) {
        if (head.next==null){
            return true;
        }
        //得到中心位置
        ListNode half = getHalf(head);
        //反转中心位置之后的链表
        ListNode reversalList = getReversalList(half.next);

        ListNode left=head;
        ListNode mid=reversalList;
        //设置result变量是为了之后有机会将反转的链表复原 否则在判断到不是回文的时候就可以直接返回false
        boolean result=true;
        while (mid!=null){
            if (left.val!= mid.val){
                result=false;
                break;//退出这个while循环
            }
            left=left.next;
            mid=mid.next;
        }
        //还原链表
        half.next=getReversalList(reversalList);
        return result;
    }

    //得到反转链表
    private ListNode getReversalList(ListNode head) {
        ListNode cur=head;//当前节点
        ListNode pre=null;//当前节点的前一个节点
        while (cur!=null){
            ListNode next=cur.next;//保存当前节点的下一个节点
            cur.next=pre;//当前节点的next节点指向前一个节点
            pre=cur;//更新前一个节点
            cur=next;//更新当前节点
        }
        return pre;
    }

    //使用快慢指针得到链表的中心位置
    private ListNode getHalf(ListNode head){
        ListNode slow=head;//慢指针 一次移动一个节点
        ListNode fast=head;//快指针 一次移动两个节点
        while (fast.next!=null&&fast.next.next!=null){
            fast=fast.next.next;
            slow=slow.next;
        }
        //当遍历完链表后 slow指向的位置就是链表的中心位置
        return slow;
    }
}

3.练习

(1)删除排序链表中的重复元素(83)

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

输入:head = [1,1,2]
输出:[1,2]

输入:head = [1,1,2,3,3]
输出:[1,2,3]
public class Solution {

    public static void main(String[] args) {
        ListNode list1=new ListNode(1,new ListNode(1,new ListNode(2,new ListNode(3))));
        Solution solution=new Solution();
        ListNode listNode = solution.deleteDuplicates(list1);
        while (listNode!=null){
            System.out.print(listNode.val+" ");
            listNode=listNode.next;
        }
    }

    public ListNode deleteDuplicates(ListNode head) {
        if (head==null||head.next==null){
            return head;
        }
        ListNode cur=head;//当前节点
        while (cur!=null&&cur.next!=null){
            if (cur.val==cur.next.val){
                cur.next=cur.next.next;//当前节点的next节点指向next的next节点
            }else {//当当前节点的值不等于下一个节点的值时 移动当前节点
                cur=cur.next;
            }
        }
        return head;
    }
}

(2)奇偶链表(328)

给定单链表的头节点 head ,将所有索引为奇数的节点和索引为偶数的节点分别组合在一起,然后返回重新排序的列表。

第一个节点的索引被认为是 奇数 , 第二个节点的索引为 偶数 ,以此类推。

请注意,偶数组和奇数组内部的相对顺序应该与输入时保持一致。

你必须在 O(1) 的额外空间复杂度和 O(n) 的时间复杂度下解决这个问题。

输入: head = [1,2,3,4,5]
输出: [1,3,5,2,4]
public class Solution {

    public static void main(String[] args) {
        ListNode list1=new ListNode(1,new ListNode(2,new ListNode(3,new ListNode(4,new ListNode(5)))));
        Solution solution=new Solution();
        ListNode listNode = solution.oddEvenList(list1);
        while (listNode!=null){
            System.out.print(listNode.val+" ");
            listNode=listNode.next;
        }
    }

    public ListNode oddEvenList(ListNode head) {
        if (head==null||head.next==null||head.next.next==null){
            return head;
        }
        ListNode even=head.next;//偶数链表
        ListNode curOdd=head;//奇数链表的当前节点
        ListNode curEven=even;//偶数链表得当前节点
        while (curEven!=null&&curEven.next!=null){
            curOdd.next=curEven.next;
            curOdd=curOdd.next;
            curEven.next=curOdd.next;
            curEven=curEven.next;
        }
        //奇数链表的最后一个节点的next节点指向偶数链表的头节点
        curOdd.next=even;
        return head;
    }
}

(3)删除链表的倒数第 N 个结点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]

输入:head = [1], n = 1
输出:[]

输入:head = [1,2], n = 1
输出:[1]
public class Solution {

    public static void main(String[] args) {
        ListNode list1=new ListNode(1,new ListNode(2,new ListNode(3,new ListNode(4,new ListNode(5)))));
        Solution solution=new Solution();
        ListNode listNode = solution.removeNthFromEnd(list1,2);
        while (listNode!=null){
            System.out.print(listNode.val+" ");
            listNode=listNode.next;
        }
    }

    public ListNode removeNthFromEnd(ListNode head, int n) {
        if (head.next==null){
            return null;
        }
        ListNode cur=head;//当前节点
        int count=0;//节点个数
        while (cur!=null){
            cur=cur.next;
            count++;
        }
        int res=count-n+1;//顺数删除的节点位置
        ListNode pre=new ListNode(0,head);
        cur=pre;
        for (int i=1;i<res;i++){
            cur=cur.next;
        }
        //当到需要被删除的节点的前一个节点时 next指向下一个节点的next节点
        cur.next=cur.next.next;
        return pre.next;
    }
}


//栈
public class Solution {

    public static void main(String[] args) {
        ListNode list1=new ListNode(1,new ListNode(2,new ListNode(3,new ListNode(4,new ListNode(5)))));
        Solution solution=new Solution();
        ListNode listNode = solution.removeNthFromEnd(list1,2);
        while (listNode!=null){
            System.out.print(listNode.val+" ");
            listNode=listNode.next;
        }
    }

    public ListNode removeNthFromEnd(ListNode head, int n) {
        if (head.next==null){
            return null;
        }
        ListNode pre=new ListNode(0,head);
        Deque<ListNode> stack=new LinkedList<>();
        ListNode cur=pre;
        //元素入栈
        while (cur!=null){
            stack.push(cur);
            cur=cur.next;
        }
        //弹出栈顶的n个元素
        for (int i=1;i<=n;i++){
            stack.poll();
        }
        //当前栈顶元素是需要删除元素的前一个元素 则将其的next指向需要删除元素的下一个元素
        stack.peek().next=stack.peek().next.next;
        return pre.next;
    }
}


//双指针
public class Solution {

    public static void main(String[] args) {
        ListNode list1=new ListNode(1,new ListNode(2,new ListNode(3,new ListNode(4,new ListNode(5)))));
        Solution solution=new Solution();
        ListNode listNode = solution.removeNthFromEnd(list1,2);
        while (listNode!=null){
            System.out.print(listNode.val+" ");
            listNode=listNode.next;
        }
    }

    public ListNode removeNthFromEnd(ListNode head, int n) {
        if (head.next==null){
            return null;
        }
        ListNode pre=new ListNode(0,head);
        ListNode first=head;//第一个指针 比第二个指针提前n个节点 当它到null时 第二个指针刚好是需要删除的节点
        ListNode second=pre;
        for (int i=1;i<=n;i++){
            first=first.next;
        }
        //遍历直到第一个节点指向空
        while (first!=null){
            first=first.next;
            second=second.next;
        }
        second.next=second.next.next;
        return pre.next;
    }
}

(4)排序链表(148)

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

输入:head = [4,2,1,3]
输出:[1,2,3,4]

输入:head = []
输出:[]
//自底向上归并排序 空间复杂度O(1)
public class Solution {

    public static void main(String[] args) {
        ListNode list1=new ListNode(2,new ListNode(1,new ListNode(4,new ListNode(3,new ListNode(0)))));
        Solution solution=new Solution();
        ListNode listNode = solution.sortList(list1);
        while (listNode!=null){
            System.out.print(listNode.val+" ");
            listNode=listNode.next;
        }
    }

    public ListNode sortList(ListNode head) {
        if (head==null){
            return null;
        }
        //计算链表的长度
        int length=getLength(head);
        //加一个前置节点 是为了避免head.next=null的特殊情况的判断
        ListNode preHead=new ListNode(0,head);
        for (int subLength=1;subLength<length;subLength<<=1){
            ListNode pre=preHead;//用于记录每一次不同subLength的已排序的链表的尾位置
            ListNode cur=preHead.next;//用于记录拆分链表的位置
            while (cur!=null){
                //需要排序的第一个子链表 长度为subLength
                ListNode head1=cur;
                for (int i=1;i<subLength&&cur.next!=null;i++){
                    cur=cur.next;
                }
                //需要排序的第二个子链表 长度为subLength
                ListNode head2=cur.next;
                cur.next=null;//将前一个子链表与后边的断开
                cur=head2;//第二个链表头重新赋值给cur
                for (int i=1;i<subLength&&cur!=null&&cur.next!=null;i++){
                    cur=cur.next;
                }
                //断开第二个子链表与后边链表的连接
                ListNode next=null;//记录已经排好序的子链表的结束位置
                if (cur!=null){
                    next = cur.next;//下一个需要排序的子链表的初始位置
                    cur.next=null;//断开连接
                }
                //给两个子链表排序  将每一次排好序的链表合并到pre后边
                pre.next=getMergeList(head1,head2);
                while (pre.next!=null){
                    pre=pre.next;//将指针移动到已排序的链表末尾
                }
                cur=next;//下一个需要排序的子链表的前一个位置
            }
        }
        return preHead.next;
    }

    //合并两个有序链表
    private ListNode getMergeList(ListNode head1, ListNode head2) {
        ListNode preHead=new ListNode(0);
        ListNode cur=preHead;//当前合并链表的尾节点
        while (head1!=null&&head2!=null){
            if (head1.val<= head2.val){
                cur.next=head1;
                head1=head1.next;
            }else {
                cur.next=head2;
                head2=head2.next;
            }
            cur=cur.next;//移动尾节点
        }
        if (head1!=null){
            cur.next=head1;
        }else if (head2!=null){
            cur.next=head2;
        }
        return preHead.next;
    }

    //得到链表长度
    private int getLength(ListNode head){
        int length=0;
        while (head!=null){
            head=head.next;
            length++;
        }
        return length;
    }
}


//自顶向下归并排序 空间复杂度log(n)
public class Solution {

    public static void main(String[] args) {
        ListNode list1=new ListNode(2,new ListNode(1,new ListNode(4,new ListNode(3,new ListNode(0)))));
        Solution solution=new Solution();
        ListNode listNode = solution.sortList(list1);
        while (listNode!=null){
            System.out.print(listNode.val+" ");
            listNode=listNode.next;
        }
    }

    public ListNode sortList(ListNode head) {
        return rec(head,null);
    }

    private ListNode rec(ListNode head, ListNode tail) {
        if (head==null){
            return null;
        }
        if (head.next==tail){
            head.next=null;
            return head;
        }
        //得到当前链表的中心位置的节点
        ListNode mid=getHalf(head,tail);
        ListNode list1=rec(head,mid);//递归将链表前半部分排好序
        ListNode list2=rec(mid,tail);//递归将链表前后部分排好序
        ListNode list=getMergeList(list1,list2);
        return list;
    }

    //得到当前链表的中心位置
    private ListNode getHalf(ListNode head,ListNode tail) {
        ListNode slow=head;//慢指针 一次走一个节点
        ListNode fast=head;//快指针 一次走两个节点
        while (fast!=tail){
            slow=slow.next;
            fast=fast.next;
            if (fast!=tail){
                fast=fast.next;
            }
        }
        return slow;//链表的中心位置
    }

    //合并两个有序链表
    private ListNode getMergeList(ListNode head1, ListNode head2) {
        ListNode preHead=new ListNode(0);
        ListNode cur=preHead;//当前合并链表的尾节点
        while (head1!=null&&head2!=null){
            if (head1.val<= head2.val){
                cur.next=head1;
                head1=head1.next;
            }else {
                cur.next=head2;
                head2=head2.next;
            }
            cur=cur.next;//移动尾节点
        }
        if (head1!=null){
            cur.next=head1;
        }else if (head2!=null){
            cur.next=head2;
        }
        return preHead.next;
    }

}

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

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

相关文章

力扣 2293. 极大极小游戏

题目 给你一个下标从 0 开始的整数数组 nums &#xff0c;其长度是 2 的幂。 对 nums 执行下述算法&#xff1a; 设 n 等于 nums 的长度&#xff0c;如果 n 1 &#xff0c;终止 算法过程。否则&#xff0c;创建 一个新的整数数组 newNums &#xff0c;新数组长度为 n / 2 &…

手把手带初学者快速入门 JAVA Web SSM 框架

博主也是刚开始学习SSM&#xff0c;为了帮大家节省时间&#xff0c;写下SSM快速入门博客 有什么不对的地方还请 私信 或者 评论区 指出 ​只是一个简单的整合项目&#xff0c;让初学者了解一下SSM的大致结构 项目先把框架写好&#xff0c;之后在填写内容 项目压缩包 完整的蓝奏…

浅谈phar反序列化漏洞

目录 基础知识 前言 Phar基础 Phar文件结构 受影响的函数 漏洞实验 实验一 实验二 过滤绕过 补充 基础知识 前言 PHP反序列化常见的是使用unserilize()进行反序列化&#xff0c;除此之外还有其它的反序列化方法&#xff0c;不需要用到unserilize()。就是用到了本文…

C 语言零基础入门教程(十一)

C 数组 C语言支持数组数据结构&#xff0c;它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据&#xff0c;但它往往被认为是一系列相同类型的变量。 数组的声明并不是声明一个个单独的变量&#xff0c;比如 runoob0、runoob1、…、runoob99&#xf…

【Linux】调试器 - gdb 的使用

目录 一、背景知识 二、debug 与 release 1、生成两种版本的可执行程序 2、debug 与 release 的区别 三、gdb 的使用 1、调试指令与指令集 2、源代码显示、运行与退出调试 3、断点操作 4、逐语句与逐过程 5、调试过程中的数据监视 6、调试过程中快速定位问题 一、背…

吴恩达机器学习笔记(三)逻辑回归

机器学习&#xff08;三&#xff09; 学习机器学习过程中的心得体会以及知识点的整理&#xff0c;方便我自己查找&#xff0c;也希望可以和大家一起交流。 —— 吴恩达机器学习第五章 —— 四、逻辑回归 线性回归局限性 线性回归对于分类问题的局限性&#xff1a;由于离群点…

LeetCode动态规划经典题目(九):入门

学习目标&#xff1a; 了解动态规划 学习内容&#xff1a; 1. LeetCode509. 斐波那契数https://leetcode.cn/problems/fibonacci-number/ 2. LeetCode70. 爬楼梯https://leetcode.cn/problems/climbing-stairs/ 3. LeetCode746. 使用最小花费爬楼梯https://leetcode.cn/proble…

ice规则引擎==启动流程和源码分析

启动 git clone代码 创建数据库ice&#xff0c;执行ice server里的sql&#xff0c;修改ice server的配置文件中的数据库信息 启动ice server 和ice test 访问ice server localhost:8121 新增一个app,默认给了个id为1&#xff0c;这个1可以看到在ice test的配置文件中指定…

MP503空气质量气体传感器介绍

MP503空气质量气体传感器简介MP503空气质量气体传感器采用多层厚膜制造工艺&#xff0c;在微型Al2O3陶瓷基片的两面分别制作加热器和金属氧化物半导体气敏层&#xff0c;封装在金属壳体内。当环境空气中有被检测气体存在时传感器电导率发生变化&#xff0c;该气体的浓度越高&am…

Spring Boot开发自定义的starter

目录 一、Spring Boot的starter概述 二、自定义starter的命名规则 三、自定义starter实战 1. 创建spring工程 2. 修改pom.xml 3. 编写配置类 4. 安装到本地maven仓库 5. 在其他项目中引入 6. 测试 一、Spring Boot的starter概述 SpringBoot中的starter是一种非常重要的机…

【web前端】CSS浮动

多个块级元素纵向排列找标准流&#xff0c;横向排列找浮动 浮动的特性&#xff1a; &#xff08;1&#xff09;浮动元素会脱离标准流&#xff08;脱标&#xff09; &#xff08;有的浮动&#xff0c;有的没浮&#xff09; &#xff08;2&#xff09;浮动的元素会在一行内显示…

C#中[]的几种用法

一、导入外部DLL函数 如[DllImport(“kernel32.dll”)]这叫引入kernel32.dll这个动态连接库。这个动态连接库里面包含了很多WindowsAPI函数,如果你想使用这面的函数&#xff0c;就需要这么引入。举个例子&#xff1a; [DllImport(“kernel32.dll”)] private static extern vo…

栈与队列总结

文章目录栈栈的概述栈的实现栈API设计栈代码实现栈的应用栈在系统中的应用括号匹配问题字符串去重问题逆波兰表达式问题队列队列的概述队列的实现队列的API设计队列代码实现队列的经典题目滑动窗口最大值问题求前 K 个高频元素栈 栈的概述 栈是一种基于先进后出(FILO)的数据结…

Android开发环境搭建

前面从全局和整体角度看了下Android包含哪些东西&#xff0c;自然&#xff0c;也涵盖了开发需要了解的内容&#xff0c;具体参见博文&#xff1a;从技术角度看Android大系统的构成_龙赤子的博客-CSDN博客 写完博文&#xff0c;感觉对Android开发也胸有成竹了&#xff0c;于是就…

ActiveReports.NET 17.0 Crack

ActiveReports.NET 17 添加新的 RDL 仪表板报告类型、新的 Blazor Web Designer&#xff0c;以及对 .NET 7 的全面支持。 2023 年 1 月 25 日 - 15:28新版本 特征 RDL 仪表板 - 新报告类型 RDL 仪表板提供了一种在可滚动的交互式容器中显示数据可视化控件&#xff08;例如图表、…

【Typescript学习】使用 React 和 TypeScript 构建web应用(三)所有组件

教程来自freecodeCamp&#xff1a;【英字】使用 React 和 TypeScript 构建应用程序 跟做&#xff0c;仅记录用 其他资料&#xff1a;https://www.freecodecamp.org/chinese/news/learn-typescript-beginners-guide/ 第三天 以下是视频(0:40-0:60) 的内容 目录第三天1 创建Todo…

JavaEE day6 初识JavaScript

什么是JS JS是通行在各种浏览器的一种语言&#xff0c;JAVA后端代码运行在服务器上&#xff0c;JS代码内容配合HTML&#xff0c;浏览器对JS代码进行解释运行&#xff0c;然后展现在浏览器上&#xff0c;web开发离不开JS。 一般步骤为&#xff1a;&#xff08;index.html与scr…

LinuxC—高级IO

高级IO 1 非阻塞IO/有限状态机编程 1.1 基本概念 定义 有限状态机(Finite State Machine) 缩写为 FSM&#xff0c;状态机有 3 个组成部分&#xff1a;状态、事件、动作。 状态&#xff1a;所有可能存在的状态。包括当前状态和条件满足后要迁移的状态。事件&#xff1a;也称为…

自动驾驶环境感知——视觉传感器技术

文章目录1. 摄像头的成像原理1.1 单目视觉传感器的硬件结构1.2 单目视觉的成像原理 –小孔成像模型1.3 单目视觉的成像原理 – 像素坐标系1.4 单目视觉三维坐标系转换 – 外参1.5 单目视觉的坐标系转换 – 从世界坐标点到像素坐标1.6 单目视觉的特性2. 视觉传感器的标定2.1 视觉…

CSS之精灵图

1. 精灵图 1.1 为什么需要精灵图 一个网页中往往会应用很多小的背景图像作为修饰&#xff0c;当网页中的图像过多时&#xff0c;服务器就会频繁地接收和发送请求图片&#xff0c;造成服务器请求压力过大&#xff0c;这将大大降低页面的加载速度。 为什么使用精灵图&#xff…