LeetCode热题100 (Java)(1)哈希

本章包括的题目有:

1. 两数之和 - 力扣(LeetCode)

49. 字母异位词分组 - 力扣(LeetCode)

128. 最长连续序列 - 力扣(LeetCode)

1.两数之和

思路解析:

由于要在一堆无序的数中找到两个数的和为target,只需先拿到一个值,然后匹配有没有另一个即可。由于需要返回下标,我们可以用哈希表来表示一个元素的值和下标。

遍历数组 nums,对于当前元素 nums[i]。检查哈希表中是否已存在一个值与之和为target。若存在,说明之前遍历过的某个数与当前数之和等于目标值,直接返回这两个数的索引。若不存在,将当前元素 (nums[i], i) 存入哈希表,供后续元素匹配。题目保证有且仅有一个有效解,因此循环内一定会返回结果。

代码实现:

java 复制代码
class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            int complement = target - nums[i];
            if (map.containsKey(complement)) {
                return new int[]{map.get(complement), i};
            }
            map.put(nums[i], i);
        }
        return new int[0]; // 根据题目约定,此处不会执行到
    }
}

时间复杂度O(n)

空间复杂度O(n)

2.字母的异位词分组

思路解析:

由于要对一堆字符串按照字母异位词分组,只需将每个字符串的字符排序后作为唯一标识,相同标识的字符串属于同一组。由于需要返回分组结果,我们可以用哈希表来表示一个排序后的字符串(键)和对应的原字符串列表(值)。

遍历字符串数组 strs,对于当前字符串 strs[i]:将其转换为字符数组并排序,再转换回字符串作为键 key。检查哈希表中是否已存在该键:若存在,将当前字符串添加到对应的列表中;若不存在,则先创建一个新列表再添加。最后,哈希表中所有的 value 集合即为分组结果,直接转换为 ArrayList 返回。题目不要求保持顺序,因此无需额外处理。

代码实现:

java 复制代码
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        int n = strs.length;
        Map<String, List<String>> map = new HashMap<>();
        for(int i = 0;i < n;i ++){
            char[] chars = strs[i].toCharArray();
            Arrays.sort(chars);
            String key = new String(chars);
            map.computeIfAbsent(key,k -> new ArrayList<>()).add(strs[i]);
        }
        return new ArrayList<>(map.values());
    }
}

computeIfAbsent方法会先查找是否有key,若有则获得其value(顺序表),若没有就添加key到map中,并通过后面的计算函数得到一个value存入map中作为新添加的key的值(此处为一个空顺序表),再通过add方法将对应的字符串添加其中。

map.values()的返回值是一个Collection,而不是List,所以不可以直接返回,而ArrayList的构造器可以接受Collection,所以可以构造成ArrayList再返回。

时间复杂度O( n * L log L ) //n为字符串数组的长度,L为字符串平均长度

空间复杂度O( n * L)

3.最长连续序列

思路解析:

由于要在无序数组中找到最长连续序列的长度,最朴素的想法是先排序,然后遍历。但是要求时间复杂度 O(n),因此不能做排序处理,我们可以用一个哈希集合来去重和匹配相邻的数。

我们只需将所有数字存入哈希集合,然后遍历集合中的每个数字。对于当前数字 n,若它的前驱 n-1 不存在于集合中,则说明 n 是一个连续序列的起点。从该起点开始,不断检查集合中是否存在 n+1、n+2......并累加计数。这样每个元素最多被访问两次(一次作为起点向后扩展,一次作为非起点被跳过),总体线性。最终返回最大计数即可。

代码实现:

java 复制代码
class Solution {
    public int longestConsecutive(int[] nums) {
        Set<Integer> set = new HashSet<>();
        for(int num : nums){
            set.add(num);
        }
        int result = 0;
        for (Integer n : set) {
            int mid = 1; //进循环说明当前数一定存在于原数组,所以从1开始记录结果
            if(set.contains(n - 1)){
                continue;
            }
            while(set.contains(n + 1)){
                mid ++;
                n ++;
            }
            if(mid > result) result = mid;
        }
        return result;
    }
}

时间复杂度O(n)

空间复杂度O(n)

下一章:

LeetCode热题100(Java)(2)双指针-CSDN博客

相关推荐
c++圈来了个新人2 小时前
C++类和对象(中)
c语言·开发语言·数据结构·c++·考研·算法
赵优秀一一2 小时前
Redis 基础、缓存、String/Hash
redis·缓存·哈希算法
王老师青少年编程2 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【删数问题】:删数问题2
c++·算法·贪心·csp·信奥赛
hanbr2 小时前
Leetcode刷题总结(1)
算法·leetcode·职场和发展
B站_计算机毕业设计之家2 小时前
计算机毕业设计:Python股票投资辅助决策系统 django框架 request爬虫 协同过滤算法 数据分析 可视化 大数据 大模型(建议收藏)✅
爬虫·python·深度学习·算法·django·flask·课程设计
_日拱一卒2 小时前
LeetCode:随机链表的复制
算法·leetcode·链表
菜菜的顾清寒2 小时前
力扣笔记自用
笔记·算法·leetcode
故事还在继续吗2 小时前
C++11关键特性
开发语言·c++·算法
zzzsde2 小时前
【Linux】线程概念与控制(2)线程控制与核心概念
linux·运维·服务器·开发语言·算法