LeetCode热题100(哈希篇)

news2025/1/15 21:43:46

题目出自Leetcode热题100:Leetcode热题100

文章目录

  • 1. 两数之和
    • 思路
    • 代码
      • C++
      • Java
      • Python
  • 49. 字母异位词分组
    • 思路
    • 代码
      • C++
      • Java
      • Python
  • 128. 最长连续序列
    • 思路
    • 代码
      • C++
      • Java
      • Python
  • 总结

1. 两数之和

在这里插入图片描述

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。
你可以按任意顺序返回答案。

思路

所谓两数之和,因为目标值的存在是可以相互转化的。
如:a+b = tar
那么a = a b = tar-a。
所以我们可以遍历一遍数组,把数组元素全部存入哈希表,然后再遍历一个数组通过哈希表来判断是否存在满足题意得另一个元素。
解题步骤:
1.定义一个哈希表。
2.遍历数组,将数组元素存入哈希表中,数组元素为key,下标为value。
3.再次遍历数组,通过哈希表判断当前元素是否满足题意。注意不能使用两次相同的元素。
4.返回结果。

代码

C++

Java

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] ans = new int[2];
        HashMap<Integer,Integer> cnt = new HashMap<Integer,Integer>();
        for(int i = 0;i<nums.length;++i)
        {
            cnt.put(nums[i],i);
        }
        for(int i = 0;i<nums.length;++i)
        {
            if(cnt.containsKey(target-nums[i])&&cnt.get(target-nums[i])!=i)
            {
                ans[0] = i;
                ans[1] = cnt.get(target-nums[i]);
                break;
            }
        }
        return ans;
    }
}

Python

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        cnt = dict()
        for i in range(0,len(nums)):
            cnt[nums[i]] = i
        nums.sort()
        
        l = 0
        r = len(nums)-1
        while l<r:
            if(nums[l]+nums[r]==target):
                return cnt[nums[l]],cnt[nums[r]]
            elif nums[l]+nums[r]>target:
                r-=1
            else:
                l+=1
        return -1,-1

49. 字母异位词分组

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。
在这里插入图片描述

思路

观察题目要求,我们需要把由相同字母的组成的不同单词组合给存放到一个数组中。第一个想法肯定就是哈希表,因为尽管单词的字母排列不同,但是单词的组成字母相同,这就可以让它成为key,然后我能把符合key的字母加入到哈希表当中。
那么这题的关键步骤也就出来了,只要知道这个key怎么求得。
对应key的求法,我想了3个思路,第3个最优。
版本1
开始我想到是,利用状态压缩把字母根据字母顺序存放到相应的比特位上,可是直到运行时才发现错误,毕竟字母会出现多次…。所以这是个错误版本
版本2
然后我又想到,既然版本1是因为无法记录字母的数目而错的,那么这次我把数字加上不就可以了吗。我想到是是我创建一个哈希数组来记录一个单词中每个字母出现的次数,然后再遍历这个哈希数组把这个单词的各个字母和字母出现的次数合起来当key,比如【“apple”】的key就是【“a1p2l1e1”】,这样就可以达成题目要求了,运行也通过了。但是效率还是低了。
版本3
最后我想到记录字母虽然可以满足题目要求,但是效率还是被拉慢了,还能不能优化。我想到还可以对数组排序啊,排序后的相同字母的组合单词一定相同,而且效率更高。

代码

C++

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string,vector<string>> cnt;
        for(string&s:strs)
        {
            string tmp(s);
            sort(tmp.begin(),tmp.end());
            if(cnt.find(tmp)==cnt.end())
            {
                cnt[tmp] = vector<string>();
            }
            cnt[tmp].push_back(s);
        }
        vector<vector<string>> ans;
        for(const auto&[key,value]:cnt)
        {
            ans.push_back(value);
        }
        return ans;
    }
};

Java

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        HashMap<String,List<String>> cnt = new HashMap<String,List<String>>();
        for(String s:strs){
            char[] arr = s.toCharArray();
            Arrays.sort(arr);
            String tmp = new String(arr);
            if(!cnt.containsKey(tmp)){
                cnt.put(tmp,new ArrayList<>());
            }
            cnt.get(tmp).add(s);
        }
        List<List<String>> ans = new ArrayList<>();
        Iterator<List<String>> it = cnt.values().iterator();
        for(List<String> group:cnt.values()){
            ans.add(group);
        }
        return ans;
    }
}

Python

class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        ans = defaultdict(list)
        for s in strs:
            key = "".join(sorted(s))
            ans[key].append(s)
        return list(ans.values())

128. 最长连续序列

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) 的算法解决此问题。
在这里插入图片描述

思路

假设题目没有要O(n)的时间复杂度的话,肯定就是先将数组排序后在遍历数组计算最长的连续序列。
那么该如何只用O(n)的时间复杂度来完成这道题呢?
排序的目的是为了让连续的数字在物理层面紧挨在一起,不排序的话,现在让它们逻辑上挨在一起就行了。我们可以利用哈希表来实现数字在逻辑方面挨在一起。哈希表的key就是数字,value则为包含key的最长连续序列的长度。
那么现在的问题就变成的如何用value表示包含key的最长连续序列的长度。
遍历数组,将第i位元素num插入哈希表,就存在3种情况:
仅num在哈希表中。
num-1或者num+1也在哈希表中。
num-1和num+1都在哈希表中。
因为哈希表的value存的是长度,当有新数字插入时,与其相邻的数字长度也需要改变。但是我们不需要把这个连续序列全部都修改,只需要修改这个连续序列的边缘数字,因为连续序列内的数字改变没有意义,我们不会把数字插入到连续序列内
在代码实现中,可以把上面三种情况同一实现,具体看代码。

代码

C++

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        int ans = 0;
        unordered_map<int,int> cnt;
        for(int& num : nums)
        {
            int prev = cnt.find(num-1)==cnt.end()?0:cnt[num-1];
            int suf = cnt.find(num+1)==cnt.end()?0:cnt[num+1];
            if(cnt.find(num)==cnt.end())
            {
                cnt[num]+=(prev+suf+1);
                cnt[num-prev] = cnt[num];
                cnt[num+suf] = cnt[num];
                
            }
        }
        for(auto&x:cnt)
        {
            ans = max(ans,x.second);
        }
        return ans;
    }
};

Java

class Solution {
    public int longestConsecutive(int[] nums) {
        HashMap<Integer,Integer> cnt = new HashMap<>();
        for(int num:nums){
            int prev = cnt.containsKey(num-1)?cnt.get(num-1):0;
            int suf = cnt.containsKey(num+1)?cnt.get(num+1):0;
            if(!cnt.containsKey(num)){
                cnt.put(num,suf+prev+1);
                cnt.put(num-prev,cnt.get(num));
                cnt.put(num+suf,cnt.get(num));
            }
        }
        int ans = 0;
        for(int val:cnt.values()){
            ans = Math.max(ans,val);
        }
        return ans;
    }
}

Python

class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        if len(nums) == 0:
            return 0
        cnt = dict()
        for num in nums:
            prev = cnt[num-1] if num-1 in cnt else 0
            suf = cnt[num+1] if num+1 in cnt else 0
            if not num in cnt:
                cnt[num] = prev+suf+1;
                cnt[num-prev] = cnt[num]
                cnt[num+suf] = cnt[num]
        ans = max(cnt.values())
        return ans

总结

Leetcode的热题100还是比较有代表性的。
此篇章记录我的刷图历程

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

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

相关文章

python学opencv|读取图像(三十一)缩放图像的三种方法

【1】引言 前序学习进程中&#xff0c;我们至少掌握了两种方法&#xff0c;可以实现对图像实现缩放。 第一种方法是调用cv2.resize()函数实现&#xff0c;相关学习链接为&#xff1a; python学opencv|读取图像&#xff08;三&#xff09;放大和缩小图像_python opencv 读取图…

rk3568 , buildroot , qt ,使用sqlite, 动态库, 静态库

问题说明&#xff1a; 客户反馈 &#xff0c;buildroot 系统 &#xff0c;使用qt 使用sqlite &#xff0c;有报错&#xff0c;无法使用sqlite. 测试情况说明&#xff1a; 我自己测试&#xff0c;发现&#xff0c; buildroot 自己默认就是 使能了 sqlite 的。 是否解决说明&…

Windows图形界面(GUI)-QT-C/C++ - Qt图形绘制详解

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 Qt绘图基础 QPainter概述 基本工作流程 绘图事件系统 paintEvent事件 重绘机制 文字绘制技术 基本文字绘制 ​编辑 高级文字效果 基本图形绘制 线条绘制 ​编辑 形状绘制 …

OpenArk64:Windows 系统分析与逆向工程工具详解

引言 在 Windows 系统的底层操作和逆向工程领域&#xff0c;OpenArk 是一款备受推崇的开源工具集。而 OpenArk64.exe 是 OpenArk 工具的 64 位版本&#xff0c;专门用于 64 位 Windows 系统。它提供了强大的功能&#xff0c;帮助用户深入分析系统内核、进程、文件、注册表等&a…

浅谈计算机网络02 | SDN控制平面

计算机网络控制平面 一、现代计算机网络控制平面概述1.1 与数据平面、管理平面的关系1.2 控制平面的发展历程 二、控制平面的关键技术剖析2.1 网络层协议2.1.1 OSPF协议2.1.2 BGP协议 2.2 SDN控制平面技术2.2.1 SDN架构与原理2.2.2 OpenFlow协议2.2.3 SDN控制器 一、现代计算机…

【C++】PP5015 [NOIP2018 普及组] 标题统计

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 提示数据规模与约定 &#x1f4af;方法分析方法1&#xff1a;我的做法实…

从玩具到工业控制--51单片机的跨界传奇【2】

咱们在上一篇博客里面讲解了什么是单片机《单片机入门》&#xff0c;让大家对单片机有了初步的了解。我们今天继续讲解一些有关单片机的知识&#xff0c;顺便也讲解一下我们单片机用到的C语言知识。如果你对C语言还不太了解的话&#xff0c;可以看看博主的C语言专栏哟&#xff…

线程池面试题目集合

最近面试中总是问到ThreadPoolExecutor类相关问题&#xff0c;在此集中整理下。 问题1.ThreadPoolExecutor的关键参数是哪些&#xff0c;任务添加过程中&#xff0c;内部线程是怎样构建的&#xff1f; a)任务到达时&#xff0c;线程池数目小于核心线程数corePoolSize&#xff0…

程序员独立开发竞品分析:确定网站使用什么建站系统

要确定一个网站使用的建站系统&#xff0c;可以通过以下几种方法尝试分析&#xff1a; 查看页面源代码&#xff1a; 打开网站&#xff0c;右键点击页面并选择“查看页面源代码”。在代码中查找一些常见的建站系统标志&#xff0c;例如&#xff1a; WordPress 的迹象&#xff1a…

基于Media+Unity的手部位姿三维位姿估计

使用mediapipe Unity 手部位姿三维位姿估计 参考文章 基于Mediapipe的姿势识别并同步到Unity人体模型中 MediapipeUnity3d实现虚拟手_unity mediapipe-CSDN博客 需求 我的需求就是快速、准确的跟踪手部位姿并实现一个三维显示。 主要思路 搭建mdeiapipe系统&#xff0c…

构建高性能网络服务:从 Socket 原理到 Netty 应用实践

1. 引言 在 Java 网络编程中&#xff0c;Socket 是实现网络通信的基础&#xff08;可以查看我的上一篇博客&#xff09;。它封装了 TCP/IP 协议栈&#xff0c;提供了底层通信的核心能力。而 Netty 是在 Socket 和 NIO 的基础上&#xff0c;进一步封装的高性能、异步事件驱动的…

Python入门10:高阶函数

一、什么是高阶函数 1.1、高阶函数的概念和作用&#xff1a; 高阶函数是指 接受函数作为参数 或者 返回函数 作为结果的函数。它在函数式编程中是一个重要概念&#xff08;函数式编程&#xff08;Functional Programming &#xff0c; FP &#xff09;是一 种编程范式&#xf…

python-leetcode-矩阵置零

73. 矩阵置零 - 力扣&#xff08;LeetCode&#xff09; class Solution:def setZeroes(self, matrix: List[List[int]]) -> None:"""Do not return anything, modify matrix in-place instead."""m, n len(matrix), len(matrix[0])row_zero …

MySQL数据库(SQL分类)

SQL分类 分类全称解释DDLData Definition Language数据定义语言&#xff0c;用来定义数据库对象&#xff08;数据库&#xff0c;表&#xff0c;字段&#xff09;DMLData Manipulation Language数据操作语言&#xff0c;用来对数据库表中的数据进行增删改DQLData Query Languag…

计算机网络 笔记 网络层1

网络层功能概述 主要的任务是把分组从源端传输到目的端&#xff0c;为分组交换网上的不同主句提供通信服务&#xff0c;网络层的传输单位是数据报。 主要的功能&#xff1b; 1&#xff0c;路由选择&#xff1a;路由选择指网络层根据特定算法&#xff0c;为数据包从源节点到目…

MyBatis-什么是MyBatis?以及MyBatis的快速入门。

简介 什么是 MyBatis&#xff1f; 什么是MyBatis? MyBatis是一款优秀的 持久层 框架&#xff0c;用于简化JDBC的开发。&#xff08;框架&#xff1a;是一个半成品软件&#xff0c;是一套可重用的、通用的、软件基础代码模型。在框架的基础上进行软件开发更加高效、规范、通用、…

Linux Kernel 之十 详解 PREEMPT_RT、Xenomai 的架构、源码、构建及使用

概述 现在的 RTOS 基本可以分为 Linux 阵营和非 Linux 阵营这两大阵营。非 Linux 阵营的各大 RTOS 都是独立发展,使用上也相对独立;而 Linux 阵营则有多种不同的实现方法来改造 Linux 以实现实时性要求。本文我们重点关注 Linux 阵营的实时内核实现方法! 本文我们重点关注 …

Swift 趣味开发:查找拼音首字母全部相同的 4 字成语(上)

概述 Swift 语言是一门现代化、安全、强大且还算性感的语言。在去年 WWDC 24 中苹果正式推出了秃头码农们期待许久的 Swift 6.0&#xff0c;它进一步完善了 Swift 语言的语法和语义&#xff0c;并再接再厉——强化了现代化并发模型的安全性和灵活性。 这里我们不妨用 Swift 来…

docker一张图理解

1、push 将本地的镜像上传到镜像仓库,要先登陆到镜像仓库。参数说明&#xff1a; –disable-content-trust : 忽略镜像的校验,默认开启 # 上传本地镜像myapache:v1到镜像仓库中。 docker push myapache:v1 1.2、search 从Docker Hub查找镜像。参数说明&#xff1a; –…

IoTDB 常见问题 QA 第三期

关于 IoTDB 的 Q & A IoTDB Q&A 第三期持续更新&#xff01;我们将定期汇总我们将定期汇总社区讨论频繁的问题&#xff0c;并展开进行详细回答&#xff0c;通过积累常见问题“小百科”&#xff0c;方便大家使用 IoTDB。 Q1&#xff1a;查询最新值 & null 数据相加方…