哈希法应用 空间换时间

什么时候使用哈希法当我们需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法。

HashMap<key,value> HashSet<key>

HashMap适用于需要存储键值对,并且需要通过键进行查找和访问值的场景。HashSet适用于需要存储唯一元素,并且不需要通过键进行访问的场景。

1 两数之和 +

使用nSum超出时间限制

map是一种key value的存储结构,可以用key保存数值,用value再保存数值所在的下标。

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] res=new int[2];//结果数组:都是下标
        Map<Integer,Integer> map=new HashMap<>();
        //key: temp数组中的值  value :对应下标
        for(int i=0;i<nums.length;i++){
            int temp=target-nums[i];   // 遍历当前元素,并在map中寻找是否有匹配的key
            if(map.containsKey(temp)){
                res[1]=i; //当前元素索引
                res[0]=map.get(temp); //差值元素值的下标
                  //满足判断条件,并在循环中需要跳出循环 
                break;
            }
            map.put(nums[i],i);  // 如果没找到匹配对,就把访问过的元素和下标加入到map中 值作为key
        }
    return res;
    }
}

49 字母异位词分组 (处理字符:标准化)+

由于互为字母异位词的两个字符串包含的字母相同,因此对两个字符串分别进行排序之后得到的字符串一定是相同的,故可以将排序之后的字符串作为哈希表的键

List<String> :一个字符串列表

char[] array = str.toCharArray(); 将当前字符串转换为字符数组

List是接口,不能直接实例化,需要使用常见实现类 ArrayList、LinkedLis

Map 接口是Java中用于表示键值对映射的接口。

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        // 创建一个哈希表,用于存储分组后的字母异位词
        Map<String, List<String>> map = new HashMap<>();
        // 遍历给定的字符串数组
        for (String str : strs) {
            // 将当前字符串转换为字符数组,并对字符数组进行排序
            char[] array = str.toCharArray();
            Arrays.sort(array);
            // 将排序后的字符数组转换为字符串,作为哈希表的键
            String key = new String(array);
            // 在哈希表中查找以当前键为索引的列表,如果不存在则创建一个新的列表
            List<String> list = map.getOrDefault(key, new ArrayList<String>());
            // 将当前字符串添加到对应的列表中
            list.add(str);
            // 将更新后的列表存回哈希表
            map.put(key, list);
        }
        // 返回哈希表中的所有值,即分组后的字母异位词列表
        return new ArrayList<List<String>>(map.values());
    }
}

128 最长连续序列 + (先找开头元素,然后递增) Hashset

这道题最直接的想法就是排序,排序之后连续的序列就很容易找到了。不过排序的时间复杂度是 O(NlogN),而题目要求我们时间复杂度为 O(N),这就得另想办法了。

想找连续序列,首先要找到这个连续序列的开头元素,然后递增,看看之后有多少个元素还在 nums 中,即可得到最长连续序列的长度了。

我们可以用空间换时间的思路,把数组元素放到哈希集合里面,然后去寻找连续序列的第一个元素,即可在 O(N) 时间找到答案。

class Solution { 
    public int longestConsecutive(int[] nums) {
        // 转化成哈希集合,方便快速查找是否存在某个元素
        HashSet<Integer> set = new HashSet<Integer>();
        //将数组值放入集合中
        for (int num : nums) {
            set.add(num);
        }
        //序列数不连续,只查找是不是存在
        int res = 0;
        for (int num : set) {
            if (set.contains(num - 1)) {
                // num 不是连续子序列的第一个,跳过
                continue;
            }
            // num 是连续子序列的第一个,开始向上计算连续子序列的长度
            int curNum = num;
            int curLen = 1;

            while (set.contains(curNum + 1)) {
                curNum += 1;
                curLen += 1;
            }
            // 更新最长连续序列的长度
            res = Math.max(res, curLen);
        }
        return res;
    }
}

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值