Java算法OJ(10)哈希表练习


目录

1.前言

2.正文

2.1俩数之和

2.2无重复字符的最长子串

2.3罗马数字转整数

2.4整数转罗马数字

3.小结


1.前言

哈喽大家好吖,今天来分享几道哈希表相关的练习题,操作比较基础但是思想比较重要,另外有许多思路与解法都是学习参照题解中诸位大佬的做法,都很有思路对我们很有启发性,欢迎大家在评论区多多交流,废话不多说让我们直接开始吧。

2.正文

2.1俩数之和

提交链接:

1. 两数之和 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/two-sum/description/?envType=problem-list-v2&envId=hash-table

这道题当然无脑遍历肯定能直接解出来,但既然要锻炼哈希表的熟练程度就用HashSet来完成:

  • 先初始化该哈希表。
  • 遍历,如果存在一个数组的数,满足目标值减去当下遍历到的这个数,那么存在解。
  • 如果遍历到最后都没有返回,那么无解。
class Solution {public int[] twoSum(int[] nums, int target) {Map <Integer,Integer>hashMap = new HashMap<>();for(int i = 0;i < nums.length;i++){if(hashMap.containsKey(target - nums[i])){return new int[]{hashMap.get(target - nums[i]),i};}hashMap.put(nums[i],i);}return new int[0];}
}
  • 时间复杂度

    • 遍历数组只需 O(n)O(n)O(n)。
    • 哈希表的插入和查找操作平均时间复杂度是 O(1)O(1)O(1)。
    • 总体时间复杂度:O(n)O(n)O(n)
  • 空间复杂度

    • 额外使用了一个哈希表存储数组中的元素和索引,最坏情况下需要存储 nnn 个元素。
    • 空间复杂度:O(n)O(n)O(n)

2.2无重复字符的最长子串

3. 无重复字符的最长子串 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/longest-substring-without-repeating-characters/description/?envType=problem-list-v2&envId=hash-table

这道题运用了滑动窗口的思想,即有俩个左右指针通过移动,记录答案后找到满足题意的解。 

  1. 窗口的定义

    • 滑动窗口是字符串的一个子串,窗口的两端由两个指针(iright)表示。
    • 窗口的内容始终保持无重复字符。
  2. 双指针移动规则

    • 右指针 right:用于扩展窗口,表示当前扫描到的位置。
    • 左指针 i:用于收缩窗口,解决窗口内出现重复字符的问题。
  3. 用数据结构维护窗口状态

    • 使用一个 HashSet(或哈希表)存储窗口内的字符,快速判断窗口中是否已经包含某个字符。
  4. 过程描述

    • 初始化窗口左右边界(iright),以及存储结果的变量(ans)。
    • 遍历字符串,用右指针逐步扩展窗口;如果窗口内出现重复字符,用左指针逐步缩小窗口,直到窗口重新无重复。
    • 在每一步中,更新窗口的长度并维护最长子串的长度。
  5. 结束条件

    • 当右指针到达字符串末尾时,遍历结束,返回最长子串的长度。
class Solution {public int lengthOfLongestSubstring(String s) {Set<Character> set = new HashSet<Character>();int right = 0;int ans = 0;for(int i = 0;i < s.length();i++){if(i != 0){set.remove(s.charAt(i - 1));//左指针}while(right < s.length() && !set.contains(s.charAt(right))){set.add(s.charAt(right));right++;}ans = Math.max(ans,(right - i));}return ans;}
}
  • 时间复杂度

    • 每个字符至多被访问两次(一次被左指针移除,一次被右指针添加)。
    • 总时间复杂度为 O(n)O(n)O(n)。
  • 空间复杂度

    • 使用了 HashSet 存储字符,空间复杂度为 O(k)O(k)O(k)。

2.3罗马数字转整数

13. 罗马数字转整数 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/roman-to-integer/description/?envType=problem-list-v2&envId=hash-table

思路如下:

首先我们先认真读题,理解罗马数字的一些规则。

  • 罗马数字使用字符表示数值:
    I=1, V=5, X=10, L=50, C=100, D=500, M=1000
  • 大部分情况下,罗马数字字符按照从左到右从大到小排列,并直接相加。
    • 如:VII = 5 + 1 + 1 = 7
  • 但在特定情况下,较小值的字符出现在较大值字符的左边时,表示减法。
    • 如:IV = 5 - 1 = 4IX = 10 - 1 = 9

算法设计:

  • 利用一个哈希表(HashMap)存储罗马字符和整数值之间的映射关系。
  • 遍历字符串,每次提取当前字符的值,并判断是否需要减去还是加上该值。
    • 如果当前字符的值小于下一个字符的值(value < next_value),说明需要减去当前值。
    • 否则,将当前值加到结果中。

算法实现步骤

  1. 初始化映射表:将每个罗马字符对应的值存入一个哈希表中,便于快速查找。
  2. 遍历字符串
    • 当前字符值(value)与下一个字符值(next_value)进行比较:
      • 如果 value < next_value,结果减去当前值;
      • 否则,结果加上当前值。
    • 循环直到字符串结束。
  3. 返回结果:遍历完成后,累积的结果即为整数值。
class Solution {public int romanToInt(String s) {Map<Character, Integer> map = new HashMap<Character, Integer>() {{put('I', 1);put('V', 5);put('X', 10);put('L', 50);put('C', 100);put('D', 500);put('M', 1000);}};int ans = 0;int n = s.length();for(int i = 0;i < s.length();i++){int value = map.get(s.charAt(i));if(i < n - 1 && value < map.get(s.charAt(i + 1))){ans -= value;}else {ans += value;}}return ans;}
}
  • 时间复杂度:O(n)O(n)O(n),其中 nnn 是罗马数字字符串的长度,每个字符只访问一次。
  • 空间复杂度:O(1)O(1)O(1),哈希表的大小是固定的,与输入规模无关。

2.4整数转罗马数字

12. 整数转罗马数字 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/integer-to-roman/description/?envType=problem-list-v2&envId=hash-table

这道题比较关键的是把这个哈希表建立出来,题目中给的并不够,只罗列出关键的 7 种数字字符,加上 6 种特殊数字所对应的罗马数字,就足够了:


建立映射关系:

  • 使用两个数组 valuessymbols 分别存储数值与对应的罗马符号,并按照数值从大到小排列。

遍历处理

  • 从高到低依次处理每一个罗马数字的数值和符号。
  • 如果当前数值可以被整数 num 包含,减去该值,并将对应的罗马符号添加到结果字符串中。
  • 重复处理当前符号,直到 num 小于该数值。

提前结束

  • 如果整数 num 减为 0,则提前退出循环以优化效率。

返回结果

  • 最终拼接完成后返回结果字符串。
class Solution {// 定义数值与罗马数字的对应关系int[] values = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};String[] symbols = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};public String intToRoman(int num) {StringBuilder roman = new StringBuilder(); // 使用 StringBuilder 拼接字符串for (int i = 0; i < values.length; ++i) {while (num >= values[i]) {num -= values[i];               // 减去当前数值roman.append(symbols[i]);       // 添加对应的罗马符号}if (num == 0) break;                // 如果数字为 0,提前退出循环}return roman.toString();                // 返回最终罗马数字}
}
  • 时间复杂度:O(1)O(1)O(1)
    罗马数字的种类和数量是固定的,因此算法的循环次数是常数,与输入大小无关。

  • 空间复杂度:O(1)O(1)O(1)
    除了固定大小的数组和结果字符串外,额外的空间使用量与输入无关。

3.小结

今天的分享到这里就结束了,喜欢的小伙伴不要忘记点点赞点个关注,你的鼓励就是对我最大的支持,加油!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二叉树:堆的建立和应用

在建立堆之前&#xff0c;我们要知道什么是树和二叉树 树 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个结点组成的一个具有层次关系的集合&#xff0c;之所以把它叫做树&#xff0c;是因为它长得像一棵倒挂的树&#xff0c;也就是根在上面&…

oracle的静态注册和动态注册

oracle的静态注册和动态注册 静态注册&#xff1a; 静态注册 : 指将实例的相关信息手动告知 listener 侦 听 器 &#xff0c; 可以使用netmgr,netca,oem 以及直接 vi listener.ora 文件来实现静态注册&#xff0c;在动态注册不稳定时使用&#xff0c;特点是&#xff1a;稳定&…

postgresql按照年月日统计历史数据

1.按照日 SELECT a.time,COALESCE(b.counts,0) as counts from ( SELECT to_char ( b, YYYY-MM-DD ) AS time FROM generate_series ( to_timestamp ( 2024-06-01, YYYY-MM-DD hh24:mi:ss ), to_timestamp ( 2024-06-30, YYYY-MM-DD hh24:mi:ss ), 1 days ) AS b GROUP BY tim…

调试器 gdb/cgdb 的使用

一. touch mycode.c vim mycode.c cgdb 下载 Ubuntu&#xff1a;sudo apt-get install -y cgdb Centos: sudo yum install -y cgdb Linux 下我们编译好的代码无法直接调试 g/gcc 默认的工作模式是release模式 程序要调试&#xff0c;必须是debug模式&#xff0c;编译时…

通过DataWorks实现MaxCompute跨项目迁移

本文为您介绍如何配置不同MaxCompute项目并实现数据迁移。 背景信息 本文使用的被迁移的原始项目为教程《简单用户画像分析&#xff08;MaxCompute版&#xff09;》中的WorkShop2023项目&#xff0c;您需要再创建一个迁移目标项目&#xff0c;用于存放原始项目的表、资源、配置…

【Linux】安装cuda

一、安装nvidia驱动 # 添加nvidia驱动ppa库 sudo add-apt-repository ppa:graphics-drivers/ppa sudo apt update# 查找推荐版本 sudo ubuntu-drivers devices# 安装推荐版本 sudo apt install nvidia-driver-560# 检验nvidia驱动是否安装 nvidia-smi 二、安装cudatoolkit&…

Vue.js 学习总结(14)—— Vue3 为什么推荐使用 ref 而不是 reactive

前言 ref 和 reactive 是 Vue3 中实现响应式数据的核心 API。ref 用于包装基本数据类型&#xff0c;而 reactive 用于处理对象和数组。尽管 reactive 似乎更适合处理对象&#xff0c;但 Vue3 官方文档更推荐使用 ref。 我的想法&#xff0c;ref就是比reactive好用&#xff0c;…

ctfshow-Misc入门(1-16)

misc1 查看图片得到flag misc2 1、打开文本&#xff0c;发现以“塒NG”开头 3、修改文件格式为png格式 4、查看图片&#xff0c;得到flag *遇到的问题&#xff1a;无法直接修改后缀名 *解决方法&#xff1a;需要点击文件夹&#xff0c;然后点击查看&#xff0c;将文件拓…

自动驾驶概念

1.线控底盘 由五大系统构成&#xff1a;线控转向、线控制动系统、线控换挡、线控油门踏板以及线控悬架。 2.自动驾驶分级 L1级别&#xff0c;也被称作驾驶支援阶段。在这一阶段&#xff0c;车辆系统能够根据驾驶环境来辅助驾驶者进行方向盘操作或减速操作中的一项&#xff0c…

【C】错误的变量定义导致sprintf()‌输出错误

问题描述 刚刚写一个用AT指令透传相关的函数&#xff0c;需要用到sprintf()‌拼接字符串。 结果发现sprintf()‌拼接出来的内容是错误的&#xff0c;简化后的代码如下&#xff1a; const char AT_CIPSEND_FIX_LENGTH_HEADER[11] "ATCIPSEND"; // 错误的&#xff0…

【Pytest+Yaml+Allure】实现接口自动化测试框架

一、框架思想 requestsyamlpytestallure实现接口自动化框架。结合数据驱动和分层思想&#xff0c;将代码与数据分离&#xff0c;易维护&#xff0c;易上手。使用yaml编写编写测试用例&#xff0c;利用requests库发送请求&#xff0c;使用pytest管理用例&#xff0c;allure生成…

内网渗透横向移动1

1.信息收集 &#xff08;1&#xff09;判断域控 shell net time /domain shell ping OWA2010CN-God.god.org &#xff08;2&#xff09;主机探测 浏览探测->网络探测 主机列表显示&#xff1a; &#xff08;3&#xff09;域用户收集&#xff1a; shell net user /domain…

C++初阶——类和对象(下)

目录 1、再探构造函数——初始化列表 2、类型转换 3、static成员 4、友元 5、内部类 6、匿名对象 7、对象拷贝时编译器的优化(了解) 1、再探构造函数——初始化列表 1. 构造函数初始化除了使用函数体内赋值&#xff0c;还有一种方式——初始化列表&#xff0c; 初始化列…

数据指标与标签在数据分析中的关系与应用

导读&#xff1a;分享数据指标体系的文章很多&#xff0c;但讲数据标签的文章很少。实际上&#xff0c;标签和指标一样&#xff0c;是数据分析的左膀右臂&#xff0c;两者同样重要。实际上&#xff0c;很多人分析不深入&#xff0c;就是因为缺少对标签的应用。今天系统的讲解下…

Exploring Prompt Engineering: A Systematic Review with SWOT Analysis

文章目录 题目摘要简介方法论背景相关工作评估结论 题目 探索快速工程&#xff1a;基于 SWOT 分析的系统评价 论文地址&#xff1a; https://arxiv.org/abs/2410.12843 摘要 在本文中&#xff0c;我们对大型语言模型 (LLM) 领域的提示工程技术进行了全面的 SWOT 分析。我们强…

Android 常用命令和工具解析之内存相关

目录 1 基本概念 1.1 PSS & RSS & USS & VSS 1.1.1 PSS 1.1.2 RSS 1.2 Dirty & Clean & SwapPss 1.2.1 Private Dirty 1.2.2 Private Clean 1.2.3 SwapPss Dirty 1.3 Swap & buffers & cache 1.3.1 Swap 1.3.2 buffers 1.3.3 cache 2…

使用Go 语言连接并操作 MySQL 数据库

新建项目&#xff0c;我这里使用的vscode&#xff1a; 1.新建项目初始化&#xff1a; 手动创建工程文件夹go安装目录->src->projectName 在项目下创建 main.go文件&#xff1a; 在vscode中点击文件->打开文件夹&#xff0c;选择刚刚新建的文件夹。打开后&#xff0…

YOLOv11融合[NeurlS2022]递归门控卷积gnconv模块及相关改进思路

YOLOv11v10v8使用教程&#xff1a; YOLOv11入门到入土使用教程 YOLOv11改进汇总贴&#xff1a;YOLOv11及自研模型更新汇总 《HorNet: Efficient High-Order Spatial Interactions with Recursive Gated Convolutions》 一、 模块介绍 论文链接&#xff1a;https://arxiv.org…

从零开始-VitePress 构建个人博客上传GitHub自动构建访问

从零开始-VitePress 构建个人博客上传GitHub自动构建访问 序言 VitePress 官网&#xff1a;VitePress 中文版 1. 什么是 VitePress VitePress 是一个静态站点生成器 (SSG)&#xff0c;专为构建快速、以内容为中心的站点而设计。简而言之&#xff0c;VitePress 获取用 Markdown…

使用Notepad++工具去除重复行

使用Notepad工具去除重复行 参考链接&#xff1a;https://blog.csdn.net/londa/article/details/108981396 一 、使用正则表达式 1、对文本进行排序&#xff0c;让重复行排在一起 2、使用正则表达式替换&#xff08;注意&#xff09;^(.*?)$\s?^(?.*^\1$) 在替换时选择正…