[Java][算法 哈希]Day 01---LeetCode 热题 100---01~03

LeetCode 热题 100---01~03   ------->哈希

第一题  两数之和

思路

最直接的理解就是   找出两个数的和等于目标数   这两个数可以相同 但是不能是同一个数字(从数组上理解就是内存上不是同一位置)

解法一:暴力法

暴力解万物 按照需求  我们需要将数组的任意不同位置的数两两相加 再去判断是否等于目标数target 那么很显然 利用for循环的嵌套 第一层for循环从头遍历到尾 表示第一个数字 ;第二个数从第一个数的后一位置开始遍历到尾部,表示第二个数字

因为题目中明确说明了每种输入只会对应一个答案  所以找到之后就可以直接返回了

那么对应的代码就是

class Solution {public int[] twoSum(int[] nums, int target) {int n = nums.length;for (int i = 0; i < n; ++i) {for (int j = i + 1; j < n; ++j) {if (nums[i] + nums[j] == target) {return new int[]{i, j};}}}return new int[0];}
}

时间复杂度为O(N^2)

解法二:双指针法

上述时间复杂度之所以高 是因为我们查找第二个数采用的也是循环 就导致了循环的嵌套,如果想降低时间复杂度,那么就需要降低第二个数的查找时间

其实这个思路也比较简单 就是我们先将数组进行排序 保证从小到大/从大到小排序(这里我们排从小到大),那么 我们就可以最开始从数组最左侧A和最右侧B的两个数据开始相加得到sum  如果sum>target 那么说明我们需要讲两个加数变小,已知一个加数A已经是最小 那么只能让B往前走一位从而减小数据(当然 如果倒数第二个数据和最后一个数据等大  自然得出来的结果还是会大于target  但是不妨碍我们继续判断),反之  如果sum<target 那么就需要增大加数,只有加数A能够增大 所以就需要将加数A向右移动一位,依此类推,直到找到数据

class Solution {public int[] twoSum(int[] nums, int target) {ArrayList<Integer> list=new ArrayList<>();for (int num : nums) {list.add(num);}int[] dest = Arrays.copyOf(nums, nums.length);Arrays.sort(dest);int slow=0;int fast=nums.length-1;while(slow!=fast){int sum=dest[slow]+dest[fast];if(sum==target){int i = list.indexOf(dest[slow]);int j = list.lastIndexOf(dest[fast]);return new int[]{i,j};}else if(sum<target){slow++;}else if(sum>target){fast--;}}return new int[]{};}
}

可以看到  时间复杂度确实变小了  但是变化不多

解法三:哈希

这才是这个题目的出题本意  使用Hash来进行判断

同解法二,我们需要的是减少第二个数字的查询时间,我们可以将每个数存入Hash表中,然后通过target-A=B来得到B 然后判断在Hash表中是否存在B即可  因为Hash的缘故 第二个数据被查询的时间减少了

因为要找寻的是下表  我们利用Map数据结构 数据作为Key  下标作为Value  这样我们就可以通过key来找到下标

那么我们遍历一遍数组 作为第一个数A 然后通过containsKey(T   Key)方法来判断是否存在第二个数据B  如果存在 就直接通过get方法获得B的下标返回即可

如果不存在 就将该数放到Map中  之所以先判断后放入 是防止先放入之后  会出现自己和自己相加等于target的情况

class Solution {public int[] twoSum(int[] nums, int target) {Map<Integer, Integer> hashtable = new HashMap<Integer, Integer>();for (int i = 0; i < nums.length; ++i) {if (hashtable.containsKey(target - nums[i])) {return new int[]{hashtable.get(target - nums[i]), i};}hashtable.put(nums[i], i);}return new int[0];}
}

第二题  字母异位词分组

思路  

首先  字母异位词就是指  对一个单词重新排列顺序后 得到一个新的单词  在这个题目中  可以理解为  给你一个字符串数组  判断该数组中哪些元素是由同一些字母组成的 

例如示例一   eat  和 ate  和tea 三个元素都是由  a  e   t 组合而成 所以他们三个归为一个数组中

如此一来 我们只需要想办法  将各个方式组成的元素 用不重复方法标识出来即可 

最好的方法就是统计字母次数  

解法一:编码-分类

我们对每一个元素遍历  然后利用  每个单词-‘a’ 得到ASCII码差值  对应一个int[26] 数组arr中的每一个数据,简单理解就是a对应arr[0]  b对应arr[1]......以此类推  最后  由相同的字母组成的单词所得到的arr数据肯定相同  然后我们将arr转化为字符串String 作为标识的key  value采用List<String> 将同一类的单词都存入到这个Map<String,List<String>> map=new HashMap<>()中即可

class Solution {public List<List<String>> groupAnagrams(String[] strs) {List<List<String>> endList=new ArrayList<>();//最终返回的ListMap<String,List<String>> map=new HashMap<>();
// 遍历整个字符串数组进行操作for (String str : strs) {String code=getCode(str);  // 求出每个元素对应的code  作为标识key
// 判断该key是否存在 如果存在 就放到对应的List中 反之 如不存在 就创造一个新的key并new一个新List将该元素放入if(map.get(code)!=null){  map.get(code).add(str);}else{map.put(code,new ArrayList<>());map.get(code).add(str);}}
//最后遍历整个Map  将value取出来即可map.forEach((x,y)->endList.add(y));return endList;}public static String getCode(String str){char[] charArray = str.toCharArray();int [] arr=new int[26];for (char c : charArray) {arr[c-'a']++;}return Arrays.toString(arr);}
}

解法二:排序

如果两个单词是属于字母异位词,那么两者的字母组成肯定是相同的,如果字母组成是相同的,那么两者对内部单词进行同样的排序方式得到的结果也肯定是一样的,所以,我们需要对每个元素单词内部进行排序,然后将结果一样的放到一起即可

其实这种方法和上述的编码分类思想差不多,解法一是我们利用字母数量进行一个编码,我们解法二其实就是将排序后的结果作为标识编码来进行区分

class Solution {public static List<List<String>> groupAnagrams(String[] strs) {List<List<String>> endList=new ArrayList<>();Map<String,List<String>> map=new HashMap<String, List<String>>();for(String x:strs) {char[] arr=x.toCharArray();Arrays.sort(arr);String end=new String(arr);if(map.containsKey(end)) {map.get(end).add(x);}else {map.put(end,new ArrayList<String>());map.get(end).add(x);}}map.forEach((x,y)->{endList.add(y);});return endList;}
}

第三题 最长连续序列

思路

判断有无连续的序列,简单的方式就是遍历一遍,然后遍历每个数的时候,判断下一个数字是否等于前一个数字加一,等于的计数器+1,反之则归零

需要注意的是,需要考虑空数组,数组中存在相同元素的情况

解法一: 自己写的

我们自己的写法就是按照上述思路的遍历想法解题

class Solution {public int longestConsecutive(int[] nums) {if(nums.length==0) return 0; //空数组直接返回LinkedHashSet<Integer> temp = new LinkedHashSet<>();ArrayList<Integer> list=new ArrayList<>();
//我们需要set来去重  但是因为set本身是无序的  为了方便后续的比较后一位是否等于前一位加一
//就需要该集合是有序的  所以我们采用LinkedHashSet这种结构for(int x=0;x<nums.length;x++){temp.add(nums[x]);}
//去重后用List存储  方便转数组for (Integer i : temp) {list.add(i);}Integer[] array = list.toArray(new Integer[0]);int[] arr=new int[array.length];for (int i = 0; i < array.length; i++) {arr[i]=array[i];}int max=0;int number=0;Arrays.sort(arr);for (int i = 1; i < arr.length; i++) {
//遍历数组 判断前一位和后一位是否连续  连续+1  反之归零if(arr[i]==arr[i-1]+1){number++;}else{if(number>max){max=number;}number=0;}}if(number>max){max=number;}return max+1;}
}

可能会有疑问  为啥中间需要用List集合来转存一下 而不是直接Set集合temp转数组arr呢?其实也是可以的  对比两者 内存消耗和时间消耗其实差不多  temp直接转Array在某些特殊情况中会比List转Array是稍微多消耗一些资源的  所以哪怕第一段代码需要额外开销来转存到List中 但是单纯的开销空间来创造一个List和遍历集合消耗也不大

class Solution {public int longestConsecutive(int[] nums) {if(nums.length==0) return 0;LinkedHashSet<Integer> temp = new LinkedHashSet<>();for(int x=0;x<nums.length;x++){temp.add(nums[x]);}Integer[] array = temp.toArray(new Integer[0]);int[] arr=new int[array.length];for (int i = 0; i < array.length; i++) {arr[i]=array[i];}int max=0;int number=0;Arrays.sort(arr);for (int i = 1; i < arr.length; i++) {if(arr[i]==arr[i-1]+1){number++;}else{if(number>max){max=number;}number=0;}}if(number>max){max=number;}return max+1;}
}

解法二:官方解法---Hash法

官方解法还是很巧妙的,我们采取遍历的方式来找,很容易重复遍历判断相同序列

由于我们要枚举的数 x 一定是在数组中不存在前驱数 x−1 的,不然按照上面的分析我们会从 x−1x-1x−1 开始尝试匹配,因此我们每次在哈希表中检查是否存在 x−1即能判断是否需要跳过了。

增加了判断跳过的逻辑之后,时间复杂度是多少呢?外层循环需要 O(n) 的时间复杂度,只有当一个数是连续序列的第一个数的情况下才会进入内层循环,然后在内层循环中匹配连续序列中的数,因此数组中的每个数只会进入内层循环一次。根据上述分析可知,总时间复杂度为 O(n)符合题目要求。

class Solution {public int longestConsecutive(int[] nums) {Set<Integer> num_set = new HashSet<Integer>();for (int num : nums) {num_set.add(num);}int longestStreak = 0;for (int num : num_set) {if (!num_set.contains(num - 1)) {int currentNum = num;int currentStreak = 1;while (num_set.contains(currentNum + 1)) {currentNum += 1;currentStreak += 1;}longestStreak = Math.max(longestStreak, currentStreak);}}return longestStreak;}
}

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

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

相关文章

报错ValueError: Unknown CUDA arch (8.6) or GPU not supported

文章目录 问题描述解决方案参考文献 问题描述 报错 ValueError: Unknown CUDA arch (8.6) or GPU not supported 本人显卡为 RTX 3060&#xff0c;CUDA 为 10.2&#xff0c;PyTorch 为 1.5 解决方案 修改 C:\Users\Administrator\Envs\test\Lib\site-packages\torch\utils\c…

【PyQt】08 - 编辑Tab顺序

文章目录 前言一、Tab顺序二、编辑Tab顺序总结 前言 介绍了什么是Tab顺序&#xff0c;以及如何修改Tab顺序。 一、Tab顺序 当你的界面设计好之后&#xff0c;在输入栏按住Tab按键&#xff0c;他会按照你摆放的顺序一次转跳 二、编辑Tab顺序 方法一 然后鼠标左击就可以改变…

前端JavaScript篇之对this对象的理解

目录 对this对象的理解1. 函数调用模式&#xff1a;2. 方法调用模式&#xff1a;3. 构造器调用模式&#xff1a;4. apply、call和bind调用模式&#xff1a; 对this对象的理解 在JavaScript中&#xff0c;this关键字是一个非常重要的概念&#xff0c;它用于指向当前执行上下文中…

【CV论文精读】EarlyBird: Early-Fusion for Multi-View Tracking in the Bird’s Eye View

【CV论文精读】EarlyBird: Early-Fusion for Multi-View Tracking in the Bird’s Eye View 0.论文摘要 多视图聚合有望克服多目标检测和跟踪中的遮挡和漏检挑战。多视图检测和3D对象检测中的最新方法通过将所有视图投影到地平面并在鸟瞰视图&#xff08;BEV&#xff09;中执…

面试经典150题 -- 栈(总结)

总的链接 面试经典 150 题 - 学习计划 - 力扣&#xff08;LeetCode&#xff09;全球极客挚爱的技术成长平台 关于栈 -- stack 的学习链接 c的STL中的栈 -- stack-CSDN博客 20 . 有效的括号 这题直接用栈模拟就好了; 这里用一种取巧的方法 , 当遇见左括号&#xff0c;加入右…

JAVA设计模式之建造者模式详解

建造者模式 1 建造者模式介绍 建造者模式 (builder pattern), 也被称为生成器模式 , 是一种创建型设计模式. 定义: 将一个复杂对象的构建与表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。 **建造者模式要解决的问题 ** 建造者模式可以将部件和其组装过程分开…

Dynamo批量处理多个Revit文件?

Hello大家好&#xff01;我是九哥~ 最近很多小伙伴都在咨询Dynamo如何批量处理多个Revit文件&#xff0c;之前写过一篇《Dynamo批量修改多文件项目基点参数》&#xff0c;利用的是后台打开Revit的方式&#xff0c;可以实现一些批量操作的功能。 但是这个方法&#xff0c;对于一…

物理信息神经网络(PINN): 将物理知识融合到深度学习中

物理信息神经网络&#xff08;PINN&#xff09;: 将物理知识融合到深度学习中 物理信息神经网络&#xff08;PINN&#xff09;简介PINN的工作原理PINN模型如何利用物理法则指导模型训练1. 定义物理问题和相应的物理定律2. 构建神经网络3. 定义损失函数数据误差项 (Data-fidelit…

IoC原理

Spring框架的IOC是基于Java反射机制实现的&#xff0c;那具体怎么实现的&#xff0c;下面研究一下 反射 Java反射机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调用它的任意方法…

多 split 窗口 in Gtkmm4

文章目录 效果预览实现概要源代码 效果预览 实现概要 使用Gtk::Paned虽然 Paned 只能装两个子控件, 但是我可以嵌套 paned1 装 box1 和 box2 paned2 装 paned1 和 box3 源代码 #include <gtkmm.h> class ExampleWindow : public Gtk::Window { public:ExampleWindow()…

大模型基础架构的变革:剖析Transformer的挑战者(下)

上一篇文章中&#xff0c;我们介绍了UniRepLKNet、StripedHyena、PanGu-π等有可能会替代Transformer的模型架构&#xff0c;这一篇文章我们将要介绍另外三个有可能会替代Transformer的模型架构&#xff0c;它们分别是StreamingLLM、SeTformer、Lightning Attention-2&#xff…

07 A B 从计数器到可控线性序列机

07. A.从计数器到可控线性序列机 让LED灯按照亮0.25秒。灭0.75秒的状态循环亮灭让LED灯按照亮0.25秒&#xff0c;灭0.5秒&#xff0c;亮0.75秒&#xff0c;灭1秒的状态循环亮灭让LED灯按照指定的亮灭模式亮灭&#xff0c;亮灭模式未知&#xff0c;由用户随即指定。以0.25秒为一…

高职单招怎么搜答案? #经验分享#微信#笔记

当今社会&#xff0c;随着信息技术的迅猛发展&#xff0c;大学生们在学习过程中面临着各种各样的困难和挑战。而在这些挑战中&#xff0c;面对繁重的作业和复杂的题目&#xff0c;大学生搜题软件应运而生 1.题老大 这是一个公众号 亿级数量题库&#xff0c;可截图搜题&#…

动态SQl简单创建

创建pojo实体类&#xff0c;使用lombok注解 package com.example.pojo;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;import java.time.LocalDate; import java.time.LocalDateTime;Data NoArgsConstructor AllArgsConstructor pu…

Maven私服部署与JAR文件本地安装

Nexus3 是一个仓库管理器&#xff0c;它极大地简化了本地内部仓库的维护和外部仓库的访问。 平常我们在获取 maven 仓库资源的时候&#xff0c;都是从 maven 的官方&#xff08;或者国内的镜像&#xff09;获取。团队的多人员同样的依赖都要从远程获取一遍&#xff0c;从网络方…

【每日一题】LeetCode——反转链表

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f64f;小杨水平有…

MySQL ——group by子句使用with rollup

group by 子句使用with rollup关键字之后&#xff0c;具有分组加和的功能。即&#xff1a;在所有的分组记录之后&#xff0c;自动新增一条记录&#xff0c;从全局计算所有记录的数据。 0 问题描述 求出每年的学生平均成绩&#xff0c;及历史至今的平均成绩&#xff0c;结果保留…

c++二叉树寒假特训题目(2)

hello&#xff0c;我是Joseph&#xff0c;今天推出第二期c二叉树寒假特训题目。 第一期传送门 第一期答案传送门 这期有7题&#xff0c;目录如下。 目录 题目 二叉树结点查找 二叉树是否对称 ​编辑 二叉排序树 层次遍历 根据前序中序求后序 二叉树高度 ​编辑 二…

【机器学习】合成少数过采样技术 (SMOTE)处理不平衡数据(附代码)

1、简介 不平衡数据集是机器学习和人工智能中普遍存在的挑战。当一个类别中的样本数量明显超过另一类别时&#xff0c;机器学习模型往往会偏向大多数类别&#xff0c;从而导致性能不佳。 合成少数过采样技术 (SMOTE) 已成为解决数据不平衡问题的强大且广泛采用的解决方案。 …

核心篇-OSPF技术之序(上)

文章目录 一. 实验专题1.1. 实验1&#xff1a;配置单区域OSPF1.1.1. 实验目的1.1.2. 实验拓扑1.1.3. 实验步骤&#xff08;1&#xff09;配置地址&#xff08;2&#xff09;运行OSPF 1.1.4. 实验调试&#xff08;1&#xff09;查看接口信息&#xff08;2&#xff09;查看邻居状…