LeetCode热题HOT100:单词拆分、环形链表 II、LRU 缓存

LeetCode热题HOT100

139. 单词拆分

题目:给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。
注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。
示例 1:
输入: s = “leetcode”, wordDict = [“leet”, “code”]
输出: true
解释: 返回 true 因为 “leetcode” 可以由 “leet” 和 “code” 拼接成。

思路分析: 使用一个布尔数组 dp[],大小为 s.length() + 1,其中 dp[i] 表示我们是否可以使用字典中的单词从索引0到索引i-1拆分字符串s。基本情况是 dp[0] = true,因为空字符串总是可以被拆分。然后,我们从左到右遍历字符串 s,对于每个索引 i,我们遍历所有可能的分割点 j,使得 0 <= j < i。如果 dp[j] 为 true,这意味着我们可以从0到j-1拆分字符串,且从j到i-1的子字符串在字典中,则我们可以从0到i-1拆分字符串。我们将 dp[i] 设置为true,并退出内部循环。最后,我们返回 dp[s.length()],它表示我们是否可以使用字典中的单词拆分整个字符串。

class Solution {
        // 定义一个方法,用于判断给定的字符串 s 是否可以被拆分成字典中的单词
        public boolean wordBreak(String s, List<String> wordDict) {
            // 定义一个布尔类型的数组 dp,长度为 s.length() + 1
            boolean[] dp = new boolean[s.length() + 1];
            // 将 dp[0] 设为 true,因为空字符串总是可以被拆分
            dp[0] = true;
            // 从 1 到 s.length() 遍历每个字符串
            for (int i = 1; i <= s.length(); i++) {
                // 从 0 到 i 遍历每个可能的拆分点
                for (int j = 0; j < i; j++) {
                    // 如果 dp[j] 为 true,意味着 s 的前半部分可以被拆分成字典中的单词,且 s 的后半部分也在字典中,则将 dp[i] 设为 true
                    if (dp[j] && wordDict.contains(s.substring(j, i))) {
                        dp[i] = true;
                        break;
                    }
                }
            }
            // 返回 dp[s.length()],表示 s 是否可以被拆分成字典中的单词
            return dp[s.length()];
        }
    }

142. 环形链表 II

题目:给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定
链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。
如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表
**示例 1:在这里插入图片描述
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

思路分析: 使用快慢指针,快指针每次走两步,慢指针每次走一步,如果链表存在环,那么快慢指针一定会相遇。在相遇时,我们可以通过计算快指针和慢指针走过的节点数来确定环中节点的个数。然后,将快指针重新指向头节点,让其先走 n 步,再让快慢指针同时走,相遇的节点即为环的入口节点。

public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null) { // 如果链表为空,则直接返回 null
            return null;
        }

        ListNode fast = head; // 定义快指针,指向链表头
        ListNode slow = head; // 定义慢指针,指向链表头
        boolean flag = false; // 定义标志位,判断链表是否存在环

        // 使用快慢指针判断链表是否存在环
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) { // 如果快慢指针相遇,则说明链表存在环
                flag = true; // 将标志位设为 true
                break;
            }
        }

        if (!flag) { // 如果标志位为 false,则说明链表不存在环,直接返回 null
            return null;
        } else { // 如果标志位为 true,则说明链表存在环
            int n = 1; // 定义计数器,记录环中节点的个数
            fast = fast.next;
            while (fast != slow) { // 统计环中节点的个数
                n++;
                fast = fast.next;
            }

            fast = head; // 将快指针重新指向头节点
            slow = head; // 将慢指针重新指向头节点
            for (int i = 0; i < n; i++) { // 让快指针先走 n 步
                fast = fast.next;
            }

            // 快慢指针同时走,相遇的节点即为环的入口节点
            while (fast != slow) {
                fast = fast.next;
                slow = slow.next;
            }

            return fast; // 返回环的入口节点
        }
    }
}

146. LRU 缓存

题目:请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache 类:
LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;
如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,
则应该 逐出 最久未使用的关键字。
函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。
**示例 1:
输入
[“LRUCache”, “put”, “put”, “get”, “put”, “get”, “put”, “get”, “get”, “get”]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]
解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1); // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2); // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1); // 返回 -1 (未找到)
lRUCache.get(3); // 返回 3
lRUCache.get(4); // 返回 4

思路分析: 使用双向链表和哈希表来实现LRU缓存。在双向链表中,每个节点保存了该节点的键值对,并且维护了前驱和后继指针。在哈希表中,每个键都映射到对应的节点。当访问一个键时,如果哈希表中包含该键,则将该节点移动到链表头部,并返回节点的值;如果哈希表中不包含该键,则返回-1。在插入一个键值对时,如果哈希表中不包含该键,则创建一个新节点并将其添加到链表头部和哈希表中;如果哈希表中包含该键,则删除旧节点,创建一个新节点并将其添加到链表头部和哈希表中。当缓存达到容量限制时,删除链表最后一个节点和哈希表中对应的项。

class LRUCache {
    // 双向链表和哈希表
    DoubleLinkedList doubleLinkedList;
    HashMap<Integer, Node> map;
    // 缓存最大容量
    int capacity;

    public LRUCache(int capacity) {
        // 初始化双向链表和哈希表
        doubleLinkedList = new DoubleLinkedList();
        map = new HashMap<>();
        // 初始化缓存最大容量
        this.capacity = capacity;
    }

    public int get(int key) {
        // 如果哈希表中不包含该键,则返回-1
        if (!map.containsKey(key)) {
            return -1;
        } else {
            // 如果哈希表中包含该键,则将该节点移动到链表头部,并返回节点的值
            Node cur = map.get(key);
            doubleLinkedList.delete(cur);
            doubleLinkedList.addFirst(cur);
            return cur.val;
        }
    }

    public void put(int key, int value) {
        // 创建新节点
        Node newNode = new Node(key, value);
        if (!map.containsKey(key)) {
            // 如果哈希表中不包含该键,则将新节点添加到链表头部和哈希表中
            if (map.size() == capacity) {
                // 如果缓存已满,则删除链表最后一个节点和哈希表中对应的项
                int k = doubleLinkedList.deleteLast();
                map.remove(k);
            }
            doubleLinkedList.addFirst(newNode);
            map.put(key, newNode);
        } else {
            // 如果哈希表中包含该键,则删除旧节点,将新节点添加到链表头部和哈希表中
            doubleLinkedList.delete(map.get(key));
            doubleLinkedList.addFirst(newNode);
            map.put(key, newNode);
        }
    }
}

class Node {
    // 节点键和值
    int key;
    int val;
    // 节点的前驱和后继
    Node pre;
    Node next;

    public Node(int key, int val) {
        // 初始化节点
        this.key = key;
        this.val = val;
    }
}

class DoubleLinkedList {
    // 双向链表的头节点和尾节点
    Node head;
    Node tail;

    public DoubleLinkedList() {
        // 初始化双向链表
        head = new Node(-1, -1);
        tail = new Node(-1, -1);
        head.next = tail;
        tail.pre = head;
    }

    public void addFirst(Node node) {
        // 将节点添加到链表头部
        node.next = head.next;
        node.pre = head;
        head.next.pre = node;
        head.next = node;
    }

    public int delete(Node node) {
        // 删除指定节点
        node.pre.next = node.next;
        node.next.pre = node.pre;
        return node.key;
    }

    public int deleteLast() {
        // 删除链表最后一个节点
        return delete(tail.pre);
    }
}

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

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

相关文章

一个从培训学校走出来的测试工程师自述....

简单介绍一下我自己&#xff0c;1997年的&#xff0c;毕业一年了&#xff0c;本科生&#xff0c;专业是机械制造及其自动化。 在校度过了四年&#xff0c;毕业&#xff0c;找工作&#xff0c;填三方协议&#xff0c;体检&#xff0c;入职。我觉得我可能就这么度过我平平无奇的…

D. Ehab and the Expected XOR Problem(构造 + 异或和)

Problem - D - Codeforces 给出两个整数nn和xx&#xff0c;构造一个满足以下条件的数组&#xff1a; 对于数组中的任何元素aiai&#xff0c;1≤ai<2n1≤ai<2n&#xff1b; 没有非空的子段&#xff0c;其位数XOR值等于00或xx、 它的长度ll应该是最大的。 一个序列bb是一个…

Spring更简单的读取和存储对象

1.存储对象 通过注解来替代配置&#xff0c;依然需要配置扫描包的类对象 1.配置扫描路径 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001…

Amazon Linux2部署安装Jenkins

先决条件 服务器配置要求 256 MB of RAM 1 GB of drive space (although 10 GB is a recommended minimum if running Jenkins as a Docker container) 需要部署安装JDK环境部署安装的Jenkins版本为Version 2.400 部署安装JDK 1. 下载JDK软件包 wget https://corretto.aws/…

c++积累11-强制类型转换运算符(static_cast/reinterpret_cast/const_cast/dynamic_cast)

1、背景 将类型名作为强制类型转换运算符的做法是C语言的老式做法&#xff0c;C为保持兼容而予以保留。强制类型转换是有一定风险的&#xff0c;C引入新的转换机制&#xff0c;主要为了客服C语言转换的三个缺点&#xff1b; 1、没有从形式上体现转换功能和风险的不同。 例如&a…

深度强化学习——第一次知识小结(3.5)

一、策略网络的小结&#xff1a; 重要概念回顾&#xff1a; 1、动作价值函数QΠ(st,at) 动作价值函数是未来奖励总和Ut的条件期望&#xff0c;如果已知了策略函数Π与当前的状态st&#xff0c;QΠ就可以对所有的动作a打分&#xff0c;以此来决定选择哪个a 其实顾名思义就是…

【分布式版本控制系统Git】| 国内代码托管中心-Gitee、自建代码托管平台-GitLab

目录 一&#xff1a;国内代码托管中心-码云 1. 码云创建远程库 2. IDEA 集成码云 3. 码云复制 GitHub 项目 二&#xff1a;自建代码托管平台-GitLab 1. GitLab 安装 2. IDEA 集成 GitLab 一&#xff1a;国内代码托管中心-码云 众所周知&#xff0c;GitHub 服务器在国外&…

二:伙伴系统

内核空间内存分配 目录 内核空间内存分配 伙伴系统 首先从内核空间开始&#xff0c;讲解内存管理模式。 主要分为三种方式&#xff1a; 这篇文章我们集中注意于伙伴系统 伙伴系统 解决了外部碎片问题&#xff0c;针对大块内存分配设计 Linux中的内存管理的“页”大小为4…

第三章(4):自然语言处理入门

第三章&#xff08;4&#xff09;&#xff1a;自然语言处理入门 在本节中&#xff0c;我们将在简单文本数据上&#xff08;例如一个句子上&#xff09;&#xff0c;执行一系列基本操作&#xff0c;来帮助你熟悉NLP的工作原理&#xff0c;其中一些技术在第三章&#xff08;2&…

SLIC超像素分割算法

SLIC超像素分割算法 《SLIC Superpixels》 摘要 超像素在计算机视觉应用中越来越受欢迎。然而&#xff0c;很少有算法能够输出所需数量的规则、紧凑的超级像素&#xff0c;并且计算开销低。我们介绍了一种新的算法&#xff0c;将像素聚类在组合的五维颜色和图像平面空间中&a…

腾讯云COS+SpringBOot实现文件上传下载功能

文章目录 第一步&#xff1a;在.yml文件中配置对应秘钥内容第二步&#xff1a;完成COSConfig类编写第三步&#xff1a;编写Controller类Bug提示&#xff1a; 最近一直在做一个项目&#xff0c;需要支持视频&#xff0c;音频&#xff0c;图片的上传&#xff0c;前面介绍的都是把…

2023年制造业产品经理考NPDP有什么用?

产品经理国际资格认证NPDP是新产品开发方面的认证&#xff0c;集理论、方法与实践为一体的全方位的知识体系&#xff0c;为公司组织层级进行规划、决策、执行提供良好的方法体系支撑。 【认证机构】 产品开发与管理协会&#xff08;PDMA&#xff09;成立于1979年&#xff0c;是…

beef-xss浏览器劫持

beef-xss浏览器劫持 一&#xff0c;实验拓扑图二&#xff0c;租用一台阿里云&#xff0c;搭建docker环境和beef环境1.租一台阿里云服务器&#xff0c;系统选用ubuntu&#xff0c;计时收费的那种&#xff0c;一个小时几毛钱2.开启策略组3000端口&#xff0c;5000端口4.安装docke…

交友项目【查询好友动态,查询推荐动态】实现

目录 1&#xff1a;圈子 1.1&#xff1a;查询好友动态 1.1.1&#xff1a;接口分析 1.1.2&#xff1a;流程分析 1.1.2&#xff1a;代码实现 1.2&#xff1a;查询推荐动态 1.2.1&#xff1a;接口分析 1.2.2&#xff1a;流程分析 1.2.3&#xff1a;代码实现 1&#xff1a…

十五分钟带你学会 Electron

文章目录 什么是 Electron为什么要选择 Electron安装 Electron桌面CSDN实战Electron 基础配置Electron 进程主进程渲染进程主进程与渲染进程的区别主进程与渲染进程的通信 Electron 跨平台问题Electron 部署打包应用程序发布应用程序 Electron 跨端原理总结 什么是 Electron E…

数据库实验 | 第1关:建立和调用存储过程(不带输出参数的存储过程)

任务描述 本关任务&#xff1a; 该实验是针对数据表jdxx&#xff0c;该数据表有四个字段&#xff0c;分别是省份(sf)、城市(cs)、区县(qxmc)、街道(name)。 例如&#xff0c;查询天心区(qxmc)的所有字段的值结果如图所示 任务要求 建立存储过程 dqxx(in city varchar(10),i…

QT QPainter坐标系统和坐标变换

一、坐标变换函数 QPainter 在窗口上绘图的默认坐标系统如图下图所示&#xff0c;这是绘图设备的物理坐标。为了绘图的方便&#xff0c;QPainter 提供了一些坐标变换的功能&#xff0c;通过平移、旋转等坐标变换&#xff0c;得到一个逻辑坐标系统&#xff0c;使用逻辑坐标系统…

BEV+Transformer对无人驾驶硬件体系的巨大改变

摘要&#xff1a; BEVTransformer彻底终结了2D直视图CNN时代&#xff0c;BEVTransformer对智能驾驶硬件系统有着什么样的影响&#xff1f;背后的受益者又是谁&#xff1f; 图片来源&#xff1a;特斯拉 BEVTransformer是目前智能驾驶领域最火热的话题&#xff0c;没有之一&…

【区块链】走进web3的世界-DApp如何快速接入wall

在web3中&#xff0c;wall是您进入区块链的一个标识&#xff0c;每个用户使用的wall都不近相同&#xff0c;因此接入更多的wall是很有必要的&#xff0c;从用户角度来说&#xff0c;非必要情况下&#xff0c;我是不愿意去额外下载wall的。因此今天我们来聊一下&#xff0c;DApp…

开发常用的 Linux 命令2(文件的查看、搜索和权限)

开发常用的 Linux 命令2&#xff08;文件的查看、搜索和权限&#xff09; 作为开发者&#xff0c;Linux是我们必须掌握的操作系统之一。因此&#xff0c;在编写代码和部署应用程序时&#xff0c;熟练使用Linux命令非常重要。这些常用命令不得不会&#xff0c;掌握这些命令&…