【思路详解+详细注释】小白都能看懂的力扣算法详解——哈希

一 LC1.两数之和

题目要求:

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。

你可以按任意顺序返回答案。

两数之和. - 力扣(LeetCode)

思路分析:

       对于每个元素 nums[i],我们需要找到一个与之相加等于目标值 target 的元素 target - nums[i],因此我们可以遍历数组,将所有访问过的元素及其索引值存入哈希表中,如果某个arget - nums[i]的值已经存在在哈希表中,说明已经找到了目标组合,获取该元素和哈希表中元素的索引返回即可。

完整代码示例:

class Solution {
    public int[] twoSum(int[] nums, int target) {
          // 创建一个哈希表,用于存储数组元素及其下标
        Map<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);
        }
        
        throw new IllegalArgumentException("No two sum solution");
    }
}

二 LC49.子母异位词分组

题目要求:

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

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

思路分析:

       根据题目可知,异位词就是组成子母相同的单词,因此我们可以直接对字符串内字母进行排序,找到所有排序后相同的单词。我们将排序后形成的新单词作为键,遍历数组,将其原本的字符串作为值存入,即可完成分组操作。

完整代码示例:

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
         // 创建一个哈希表,用于存储字母异位词分组
        Map<String, List<String>> map = new HashMap<>();
        
        // 遍历每个字符串
        for (String str : strs) {
            // 将字符串转换为字符数组并排序
            char[] charArray = str.toCharArray();
            Arrays.sort(charArray);
            String sortedStr = new String(charArray);
            
            // 将排序后的字符串作为键,找到对应的分组
            if (!map.containsKey(sortedStr)) {
                map.put(sortedStr, new ArrayList<>());
            }
            // 将原字符串加入该分组中
            map.get(sortedStr).add(str);
        }
        
        // 返回哈希表中所有的值,即字母异位词分组
        return new ArrayList<>(map.values());
    }
}

三 LC128.最长连续序列

题目要求:

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

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

思路分析:

       方案一:先将数组元素排序,再使用双指针遍历数组,去掉重复的元素(时间复杂度不符合要求)。

        方案二:哈希表。将所有数字都存在一个集合里,我们在集合中查询某个数字的时间复杂度只有o(1)。遍历数组中的数字,如果数字减一存在在集合中,说明该元素已经被检查过,不再重复检查。否则说明该数字是一个连续序列的起点,我们从该数字开始不断寻找数字+1是否存在在集合中,如果存在则将总长度加1,继续检查下一位数字,直到集合中不存在下一位数字。当检查结束,我们更新记录的总长度为所有记录中的最大值,再遍历检查下一个元素。

完整代码示例:

class Solution {
    public int longestConsecutive(int[] nums) {
        // 创建一个哈希集合用于存储所有的数字
        Set<Integer> numSet = new HashSet<>();
        for (int num : nums) {
            numSet.add(num);
        }
        
        int longestStreak = 0;
        
        // 遍历数组中的每一个数字
        for (int num : numSet) {
            // 如果 num-1 不在集合中,说明 num 是一个序列的起点
            if (!numSet.contains(num - 1)) {
                int currentNum = num;
                int currentStreak = 1;
                
                // 从 num 开始,不断查看 num+1、num+2...是否在集合中
                while (numSet.contains(currentNum + 1)) {
                    currentNum += 1;
                    currentStreak += 1;
                }
                
                // 更新最长连续序列的长度
                longestStreak = Math.max(longestStreak, currentStreak);
            }
        }
        
        return longestStreak;
    }
}

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值