【算法练习】leetcode链表算法题合集

news2025/1/23 4:49:21

在这里插入图片描述

链表总结

  1. 增加表头元素
  2. 倒数节点,使用快慢指针
  3. 环形链表(快慢指针)
  4. 合并有序链表,归并排序
  5. LRU缓存

算法题

删除链表元素

删除链表中的节点

LeetCode237. 删除链表中的节点

复制后一个节点的值,删除后面的节点(1->5->3->4,删除5的话,先调整为1->3->3->4,再删除第二个3的节点)

class Solution {
    public void deleteNode(ListNode node) {
        node.val = node.next.val;
        node.next = node.next.next;
    }
}
删除链表的倒数第 N 个结点

LeetCode19. 删除链表的倒数第 N 个结点

快慢节点,使用虚拟节点,删除节点

当fast的next节点到了链表外,slow的next节点是第n个节点。找到slow的next节点,删除。

class Solution_LC19 {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        ListNode slow = dummy;
        ListNode fast = dummy;
        for (int i = 0; i < n; i++) {
            fast = fast.next;
        }
        while (fast.next != null) {
            fast = fast.next;
            slow = slow.next;
        }
        slow.next = slow.next.next;
        return dummy.next;
    }

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

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

和当前节点比较值,相同则删掉,不同则下一个节点

class Solution_LC83 {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode cur = head;
        while (cur != null) {
            int val = cur.val;
            if (cur.next != null && cur.next.val == val) {
                cur.next = cur.next.next;
            } else {
                cur = cur.next;
            }
        }
        return head;
    }
}
删除排序链表中的重复元素 II(**)

LeetCode82. 删除排序链表中的重复元素 II

定义两个节点。cur节点是用来比较的节点,pre节点是用来删除的。找到cur节点,该节点和next节点不一致,pre.next=cur,等于是删除了pre和cur之间的元素。

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        ListNode pre = dummy;
        ListNode cur = head;
        while (cur != null && cur.next != null) {
            int x = cur.val;
            if (cur.next.val == x) {
                while (cur != null && cur.val == x) {
                    cur = cur.next;
                }
                pre.next = cur;
            } else {
                cur = cur.next;
                pre = pre.next;
            }
        }
        return dummy.next;
    }
}

旋转链表

反转链表

LeetCode206. 反转链表

头插法。pre和cur不断向后移动,直到cur为空,pre为最后一个节点(遍历顺序的最后一个)。

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;
        while (cur != null) {
            ListNode next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }
}
K 个一组翻转链表

LeetCode25. K 个一组翻转链表

  • 获取k个节点一组的链表

  • 翻转链表

  • pre的后面一个节点是start,end的最后一个节点是next。

class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode dummy = new ListNode(-1);
                dummy.next = head;
        ListNode pre = dummy;
        ListNode end = dummy;

        while (end.next != null) {
            for (int i = 0; i < k&&end!=null; i++) {
                end = end.next;

            }
            if (end == null) {
                    break;
                }
            ListNode next = end.next;
            ListNode start = pre.next;
            end.next = null;

            pre.next = reverse(start);

            start.next = next;
            pre = start;
            end = start;
        }
        return dummy.next;
    }

    private ListNode reverse(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;
        while (cur != null) {
            ListNode next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;

        }
        return pre;
    }
}
LeetCode61. 旋转链表

LeetCode61. 旋转链表.

  • 获取链表的尾结点

  • 尾结点连接头节点

  • 找到切割点(切割点的前一个节点)

  • 切割。获取next节点,将当前节点的next置为空,切断。

class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if (k == 0 || head == null || head.next == null) {
            return head;
        }
        ListNode cur = head;
        int n = 1;
        while (cur.next != null) {
            cur = cur.next;
            n++;
        }

        int add = n - k % n;
        if (add == n) {
            return head;
        }
        cur.next = head;
        while (add > 0) {
            cur = cur.next;
            add--;
        }

        ListNode next = cur.next;
        cur.next = null;
        return next;
    }
}

交换链表节点

LeetCode24. 两两交换链表中的节点(⭐️高频)

LeetCode24. 两两交换链表中的节点

定义虚拟头结点

获取可以交换的节点,进行节点操作

将node1节点置为前置结点,进行下一轮操作

class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dummy = new ListNode(-1, head);
        ListNode cur = dummy;

        while (cur.next != null && cur.next.next != null) {
            ListNode node1 = cur.next;
            ListNode node2 = node1.next;
            ListNode next = node2.next;
            cur.next = node2;
            node2.next = node1;
            node1.next = next;
            cur = node1;
        }
        return dummy.next;
    }
}

环形/相交/回文链表

LeetCode141. 环形链表(腾讯)

LeetCode141. 环形链表(腾讯)

使用快慢指针,如果快指针最后到达慢指针,则存在环。

public class Solution {
 public boolean hasCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) {
                return true;
            }
        }
        return false;
    }
}
LeetCode142. 环形链表II

LeetCode142. 环形链表II.

快慢指针

a+b+n(b+c)=2(a+b) --> a=(n-1)(b+c)+c

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if (slow == fast) {
                ListNode node1 = head;
                ListNode node2 = fast;
                while (node1 != node2) {
                    node1 = node1.next;
                    node2 = node2.next;
                }
                return node1;
            }
        }
        return null;
    }
}
LeetCode160.相交链表

160. 相交链表

要进行临界值判断

相交的链表后面一段是公共的,a+b+c=c+b+a。

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) {
            return null;
        }
        ListNode p1 = headA;
        ListNode p2 = headB;
        while (p1 != p2) {
            p1 = p1 == null ? headB : p1.next;
            p2 = p2 == null ? headA : p2.next;
        }
        return p1;
    }
}
LeetCode234. 回文链表

234. 回文链表

寻找中间节点,并反转前面列表

pre是反转链表的头结点,slow是后面链表的头结点。比较节点的值,判断是否回文

class Solution {
    public boolean isPalindrome(ListNode head) {
                //1-2-3-2-1
        ListNode fast = head;
        ListNode slow = head;
        ListNode pre = null;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            ListNode next = slow.next;
            slow.next = pre;
            pre = slow;
            slow = next;
        }
        if (fast != null) {
            slow = slow.next;
        }
        while (pre != null && slow != null) {
            if (slow.val != pre.val) {
                return false;
            } else {
                slow = slow.next;
                pre = pre.next;
            }
        }
        return true;
    
    }
}

链表合并

LeetCode2: 两数相加

LeetCode2: 两数相加

对应数位的值相加,计算当前节点以及向上的值。

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(-1);
        ListNode cur = dummy;
        int carry = 0;
        while (l1 != null || l2 != null || carry != 0) {
            int sum = (l1 == null ? 0 : l1.val) + (l2 == null ? 0 : l2.val) + carry;
            carry = sum / 10;
            ListNode tmp = new ListNode(sum % 10);
            cur.next = tmp;
            cur = tmp;
            l1 = l1 == null ? null : l1.next;
            l2 = l2 == null ? null : l2.next;
        }
        return dummy.next;
    }
}
LeetCode445: 两数相加II

LeetCode445: 两数相加II

使用堆栈,用于顺序相反获取值

链表的拼接和上一题不同。上一题是不断往链表后面添加元素;这一题是不断往前面添加元素。

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        Stack<Integer> stack1 = new Stack<>();
        Stack<Integer> stack2 = new Stack<>();
        while (l1 != null) {
            stack1.push(l1.val);
            l1 = l1.next;
        }
        while (l2 != null) {
            stack2.push(l2.val);
            l2 = l2.next;
        }
        int carry = 0;

        ListNode cur = null;
        while (!stack1.isEmpty() || !stack2.isEmpty() || carry != 0) {
            int sum = (stack1.isEmpty() ? 0 : stack1.pop()) + (stack2.isEmpty() ? 0 : stack2.pop()) + carry;
            carry = sum / 10;
            ListNode tmp = new ListNode(sum % 10);
            tmp.next = cur;
            cur = tmp;

        }
        return cur;

    }
}
LeetCode21: 合并两个有序链表

21. 合并两个有序链表

挨个遍历比较大小,是最容易想到的方案

使用递归。当l1.val < l2.vall1.next = mergeTwoLists(l1.next, l2);

class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode dummy = new ListNode(-1);
        ListNode cur = dummy;
        while (list1 != null && list2 != null) {
            if (list1.val < list2.val) {
                cur.next = new ListNode(list1.val);
                cur = cur.next;
                list1 = list1.next;
            } else {
                cur.next = new ListNode(list2.val);
                cur = cur.next;
                list2 = list2.next;
            }
        }
        if (list1 != null) {
            cur.next = list1;
        } else {
            cur.next = list2;
        }
        return dummy.next;
    }
}
LeetCode23: 合并K个排序链表

23. 合并 K 个升序链表

挨个遍历处理

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        ListNode ans = null;
        for (int i = 0; i < lists.length; i++) {
             ans =mergeTwoLists(ans, lists[i]);
        }
        return ans;
    }

    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        if (list1 == null || list2 == null) {
            return list1 == null ? list2 : list1;
        }
        ListNode dummy = new ListNode(-1);
        ListNode cur = dummy;
        while (list1 != null && list2 != null) {
            if (list1.val < list2.val) {
                cur.next = new ListNode(list1.val);
                cur = cur.next;
                list1 = list1.next;
            } else {
                cur.next = new ListNode(list2.val);
                cur = cur.next;
                list2 = list2.next;
            }
        }
        if (list1 != null) {
            cur.next = list1;
        } else {
            cur.next = list2;
        }
        return dummy.next;

    }
}

分治合并,将链表数组拆分成2段,处理好后合并。

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        return merge(lists, 0, lists.length - 1);
    }

    private ListNode merge(ListNode[] lists, int l, int r) {

        if (l == r) {
            return lists[l];
        }
        if (l > r) {
            return null;
        }
        int mid = (l + r) / 2;
        return mergeTwoLists(merge(lists, l, mid), merge(lists, mid + 1, r));

    }

    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        if (list1 == null || list2 == null) {
            return list1 == null ? list2 : list1;
        }
        ListNode dummy = new ListNode(-1);
        ListNode cur = dummy;
        while (list1 != null && list2 != null) {
            if (list1.val < list2.val) {
                cur.next = new ListNode(list1.val);
                cur = cur.next;
                list1 = list1.next;
            } else {
                cur.next = new ListNode(list2.val);
                cur = cur.next;
                list2 = list2.next;
            }
        }
        if (list1 != null) {
            cur.next = list1;
        } else {
            cur.next = list2;
        }
        return dummy.next;

    }
}

使用优先队列

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        //优先队列默认是小顶堆,最小的元素放在队头,即a-b
        PriorityQueue<ListNode> priorityQueue = new PriorityQueue<ListNode>((a, b) -> {
            return a.val - b.val;
        });

        for (int i = 0; i < lists.length; i++) {
            if(lists[i]!=null){
priorityQueue.add(lists[i]);
            }
            
        }
        ListNode dummy = new ListNode(-1);
        ListNode cur = dummy;
        while (!priorityQueue.isEmpty()) {
            ListNode listNode = priorityQueue.poll();
            ListNode next = listNode.next;
            cur.next = listNode;
            cur = listNode;
            if (next != null) {
                priorityQueue.add(next);
            }
        }

        return dummy.next;

    }
}
LeetCode148: 排序链表

148. 排序链表

使用优先队列,最简单。

使用归并排序。做链表拆分。

可以和回文链表做比较,必须熟悉掌握两个链表合并的逻辑。

class Solution {
    public ListNode sortList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode fast = head.next;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        ListNode next = slow.next;
        slow.next = null;
        ListNode listNode1 = sortList(head);
        ListNode listNode2 = sortList(next);
        ListNode dummy = new ListNode(-1);
        ListNode cur =dummy;
        while (listNode1 != null && listNode2 != null) {
            if (listNode1.val < listNode2.val) {
                cur.next = listNode1;
                cur = cur.next;
                listNode1 = listNode1.next;
            } else {
                cur.next = listNode2;
                cur = cur.next;
                listNode2 = listNode2.next;
            }

        }
        cur.next = listNode1 == null ? listNode2 : listNode1;
        return dummy.next;
    }
}

LRU缓存

LeetCode146. LRU 缓存

146. LRU 缓存

使用LinkedHashMap,设置accessOrder为true,最近访问的元素会排在最后。而removeEldestEntry当条件满足的时候会移除最老的元素。

class LRUCache extends LinkedHashMap<Integer, Integer> {

    private int capacity;

    public LRUCache(int capacity) {
        super(capacity, 0.75f, true);
        this.capacity = capacity;
    }

    public int get(int key) {
        return super.getOrDefault(key, -1);
    }

    public void put(int key, int value) {
        super.put(key, value);
    }

    protected boolean removeEldestEntry(Map.Entry<Integer, Integer> entry) {
        return size() > this.capacity;
    }
}

使用Hash表和双向链表

双向链表记录访问顺序,Hash表获取元素

获取元素,将元素放在最前(移除当前元素在双向链表中的原位置,放在前面)。

存放元素,如果元素已存在,进行更新值,且将元素放在最前;如果元素不存在,添加元素要判断边界,超过边界要移除最早访问的元素(从链表和Hash表中移除)。

class LRUCache extends LinkedHashMap<Integer, Integer> {

    public class DLinkedNode {
        int key;
        int val;
        DLinkedNode prev;
        DLinkedNode next;

        public DLinkedNode() {
        }

        public DLinkedNode(int key, int val) {
            this.key = key;
            this.val = val;
        }
    }

    private Map<Integer, DLinkedNode> map = new HashMap<>();

    private int size;

    private int capacity;

    private DLinkedNode head, tail;


    public LRUCache(int capacity) {
        this.capacity = capacity;
        size = 0;
        head = new DLinkedNode();
        tail = new DLinkedNode();
        head.next = tail;
        tail.prev = head;
    }

    public int get(int key) {
        DLinkedNode dLinkedNode = map.get(key);
        if (dLinkedNode == null) {
            return -1;
        } else {
            moveToHead(dLinkedNode);
            return dLinkedNode.val;
        }
    }

    private void moveToHead(DLinkedNode node) {
        removeNode(node);
        addToHead(node);

    }

    private void addToHead(DLinkedNode node) {
        DLinkedNode next = head.next;
        head.next = node;
        node.prev = head;
        node.next = next;
        next.prev = node;
    }

    private void removeNode(DLinkedNode node) {
        DLinkedNode prev = node.prev;
        DLinkedNode next = node.next;
        prev.next = next;
        next.prev = prev;
    }

    private DLinkedNode removeTail() {
        DLinkedNode prev = tail.prev;
        removeNode(prev);
        return prev;
    }

    public void put(int key, int value) {
        DLinkedNode node = map.get(key);
        if (node == null) {
            DLinkedNode newNode = new DLinkedNode(key, value);

            map.put(key, newNode);
            addToHead(newNode);
            size++;
            if (size > capacity) {
                DLinkedNode tail = removeTail();
                map.remove(tail.key);
                size--;
            }
        } else {

            node.val = value;
            moveToHead(node);
        }
    }
}

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

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

相关文章

多环境及SpringBoot项目部署

1、多环境 2、项目部署上线 原始前端 / 后端项目宝塔Linux容器容器平台 3、前后端联调 4、项目扩展和规划 多环境 程序员鱼皮-参考文章 本地开发&#xff1a;localhost&#xff08;127.0.0.1&#xff09; 多环境&#xff1a;指同一套项目代码在把不同的阶段需要根据实际…

【Vue2+3入门到实战】(17)VUE之VueCli脚手架自定认创建项目、ESlint代码规范与修复、 ESlint自动修正插件的使用 详细示例

目录 一、本节内容二、VueCli 自定义创建项目三、ESlint代码规范及手动修复1.JavaScript Standard Style 规范说明2.代码规范错误3.手动修正 四、通过eslint插件来实现自动修正 一、本节内容 VueCli脚手架自定认创建项目ESlint代码规范与修复ESlint自动修正插件 二、VueCli 自…

设备健康管理系统助力制造企业实现数字化转型

在当今快速变革的制造业环境中&#xff0c;数字化转型已成为制造企业保持竞争力和实现可持续发展的关键。在这个数字化转型的浪潮中&#xff0c;设备健康管理系统正发挥着重要的作用。设备健康管理系统通过实时监测、预测分析和智能诊断等功能&#xff0c;为制造企业提供了全面…

中医电子处方系统,西医个体诊所门诊卫生室病历记录查询软件教程

中医电子处方系统&#xff0c;西医个体诊所门诊卫生室病历记录查询软件教程 一、软件程序问答 1、电子处方软件如何快速开单&#xff1f; 如下图&#xff0c;软件以 佳易王诊所电子处方管理系统V17.1版本为例说明 在开电子处方的时候可以按单个药品开&#xff0c;也可以直…

动态规划10-多重背包

题目描述 有N种物品和一个容量为V 的背包。第i种物品最多有Mi件可用&#xff0c;每件耗费的空间是Ci &#xff0c;价值是Wi 。求解将哪些物品装入背包可使这些物品的耗费的空间 总和不超过背包容量&#xff0c;且价值总和最大。 思路分析 区别于完全背包和简单的01背包问题&…

数据的确权、流通、入表与监管研究(二)数据与流通

附&#xff1a;2023年数据资源入表白皮书下载&#xff1a; 关注WX公众号&#xff1a; commindtech77&#xff0c; 获得数据资产相关白皮书下载地址 1. 回复关键字&#xff1a;数据资源入表白皮书 下载 《2023数据资源入表白皮书》 2. 回复关键字&#xff1a;光大银行 下载 光…

牛客网面试题知识点记录-02

1.collection接口 2.在构造方法中调用方法A,若方法A被子类重写&#xff0c;则会先调用子类的方法A。举例如下题&#xff1a; 此时会输出null&#xff0c;调用顺序为&#xff1a;子类初始化&#xff0c;但是子类实现了Base&#xff0c;会先执行Base的构造方法&#xff0c;构造…

golang第五卷---包以及常用内置包归纳

包以及常用内置包归纳 包的概念math包time包sync包 Go 语言官方的包文档网站&#xff1a;包文档 包的概念 Go语言是使用包来组织源代码的&#xff0c;包&#xff08;package&#xff09;是多个 Go 源码的集合&#xff0c;是一种高级的代码复用方案。 任何源代码文件必须属于某…

2022–2023学年2021级计算机科学与技术专业数据库原理 (A)卷

一、单项选择题&#xff08;每小题1.5分&#xff0c;共30分&#xff09; 1、构成E—R模型的三个基本要素是&#xff08; B &#xff09;。 A&#xff0e;实体、属性值、关系 B&#xff0e;实体、属性、联系 C&#xff0e;实体、实体集、联系 D&#xff0e;实体、实体…

基于 CefSharp 实现一个文件小工具

I’m not saying you can’t be financially successful I’m saying have a greater purpose in life well beyond the pursuit of financial success Your soul is screaming for you to answer your true calling You can change today if you redefine what success is to …

分布式存储考点梳理 + 高频面试题

欢迎来到分布式存储模环节&#xff0c;本文我将和你一起梳理面试中分布式系统的数据库的高频考点&#xff0c;做到温故知新。 面试中如何考察分布式存储 广义的分布式存储根据不同的应用领域&#xff0c;划分为以下的类别&#xff1a; 分布式协同系统 分布式文件系统 分布式…

Android长按图标展示快捷方式

if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {new Thread(() -> {// 获取ShortcutManager实例ShortcutManager shortcutManager getSystemService(ShortcutManager.class);// 创建要添加的快捷方式ShortcutInfo.Builder shortcutBuilder new ShortcutInfo.Bui…

OpenCV实战 -- 维生素药片的检测记数

文章目录 检测记数原图经过操作开始进行消除粘连性--形态学变换总结实现方法1. 读取图片&#xff1a;2. 形态学处理&#xff1a;3. 二值化&#xff1a;4. 提取轮廓&#xff1a;5. 轮廓筛选和计数&#xff1a; 分水岭算法&#xff1a;逐行解释在基于距离变换的分水岭算法中&…

dll不能运行是什么意思,分享5种有效的修复方法

在计算机使用过程中&#xff0c;我们可能会遇到各种各样的问题&#xff0c;其中一种常见的问题是“dll不能运行”。这个问题可能会影响到我们的正常使用&#xff0c;甚至导致某些软件无法启动。那么&#xff0c;“dll不能运行是什么意思”呢&#xff1f;dll文件丢失怎么恢复&am…

【数据结构】排序之交换排序(冒泡 | 快排)

交换目录 1. 前言2. 交换排序3. 冒泡排序3.1 分析3.2 代码实现 4. 快速排序4.1 hoare版本4.1.1 分析4.1.2 hoare版本代码 4.2 挖坑法4.2.1 分析4.2.2 挖坑法代码实现 4.3 前后指针版本4.3.1 分析4.3.2 前后指针版本代码实现 1. 前言 在之前的博客中介绍了插入排序&#xff0c;…

2023-12-20 LeetCode每日一题(判别首字母缩略词)

2023-12-20每日一题 一、题目编号 2828. 判别首字母缩略词二、题目链接 点击跳转到题目位置 三、题目描述 给你一个字符串数组 words 和一个字符串 s &#xff0c;请你判断 s 是不是 words 的 首字母缩略词 。 如果可以按顺序串联 words 中每个字符串的第一个字符形成字符…

MySQL 8.0 InnoDB Tablespaces之General Tablespaces(通用表空间/一般表空间)

文章目录 MySQL 8.0 InnoDB Tablespaces之General Tablespaces&#xff08;通用表空间/一般表空间&#xff09;General tablespaces&#xff08;通用表空间/一般表空间&#xff09;通用表空间的功能通用表空间的限制 创建通用表空间&#xff08;一般表空间&#xff09;创建语法…

vue2使用svg图片

1、安装依赖包&#xff1a; npm install svg-sprite-loader --save-dev 2、新建assets/icons/svg中放置svg图片和index.js文件 svgo.yml文件 index.js import Vue from vue import SvgIcon from /components/SvgIcon// svg component// register globally Vue.component(sv…

基于ssm的4S店预约保养系统开发+vue论文

目 录 目 录 I 摘 要 III ABSTRACT IV 1 绪论 1 1.1 课题背景 1 1.2 研究现状 1 1.3 研究内容 2 2 系统开发环境 3 2.1 vue技术 3 2.2 JAVA技术 3 2.3 MYSQL数据库 3 2.4 B/S结构 4 2.5 SSM框架技术 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2 操作可行性 5 3…

HTML5和JS实现新年礼花效果

HTML5和JS实现新年礼花效果 2023兔年再见&#xff0c;2024龙年来临了&#xff01; 祝愿读者朋友们在2024年里&#xff0c;身体健康&#xff0c;心灵愉悦&#xff0c;梦想成真。 下面是用HTML5和JS实现新年礼花效果&#xff1a; 源码如下&#xff1a; <!DOCTYPE html>…