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

本章包括的题目有:

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

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

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

1.两数之和

思路解析:

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

遍历数组 nums,对于当前元素 numsi。检查哈希表中是否已存在一个值与之和为target。若存在,说明之前遍历过的某个数与当前数之和等于目标值,直接返回这两个数的索引。若不存在,将当前元素 (numsi, 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,对于当前字符串 strsi:将其转换为字符数组并排序,再转换回字符串作为键 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博客

相关推荐
To_OC6 小时前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode
To_OC6 小时前
LC 208 实现 Trie 前缀树:曾被名字劝退,写完发现是送分题
javascript·算法·leetcode
BadBadBad__AK8 小时前
线段树维护区间 k 次方和
c++·数学·算法·stl
_清歌20 小时前
DSpark 深度解读:DeepSeek-V4 如何用「半自回归」把推理速度提升 85%
算法
统计实现局20 小时前
SVD 的三步走:双对角化、Givens 收敛、排序
算法
躬行见万象20 小时前
《VLA 系列》UniLab 强化训练 | G1 机器人 |复现
算法
统计实现局20 小时前
对称不定分解(Bunch-Kaufman):为什么 Cholesky 不够用
算法
统计实现局20 小时前
dqrsl 拆解:拿着 QR 结果能算出哪 5 种东西
算法
统计实现局21 小时前
为什么 Cholesky 求逆比 Gauss-Jordan 快一倍——行列式溢出防护详
算法