Hot100-哈希法

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

在做面试题目的时候遇到需要判断一个元素是否出现过的场景应该第一时间想到哈希法

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result = new int[2];
        for (int i = 0; i < nums.length;i++){
            for (int j= nums.length-1; j>=i+1; j--){
                if (nums[i]+nums[j]==target){
                    result[0] = i;
                    result[1] = j;
                }
            }
        }
        return result;
    }
}

注意:

1.int是基本属性,所以直接用nums.length,不用调用方法()

2.新建数组时要规定好数组的长度:int[] result = new int[2]

3.for循环是nums.length - 1

使用哈希法优化:

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

本题呢,我就需要一个集合来存放我们遍历过的元素,然后在遍历数组的时候去询问这个集合,某元素是否遍历过,也就是 是否出现在这个集合。

那么我们就应该想到使用哈希法了。

因为本题,我们不仅要知道元素有没有遍历过,还要知道这个元素对应的下标,需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result = new int[2];
        //剪枝
        if (nums==null || nums.length==0){
            return null;
        }
        //查询:使用哈希法
        //Map,key value, key放被加数,value放索引值(最后result里面放的是索引值)
        Map<Integer, Integer> map= new HashMap();
        for (int i = 0; i < nums.length ;i++){
            int temp = target - nums[i];
            if (map.containsKey(temp)){
                result[0]=i;
                result[1]=map.get(temp);
                break;
            }    
          map.put(nums[i], i); 
          // 如果这一轮没找到匹配对,就把访问过的元素和下标加入到map中;方便后续匹配 temp = target - nums[i];

        }
        return result;
    }
}

注意:

1.map的key存储被加数,value存储索引

2.用到了map的几个方法:

map.containsKey(temp):判断map中是否包含需要的key

map.get(temp):获取temp对应的value

map.put(nums[i], i):将键值对存入map

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

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
// 由于互为字母异位词的两个字符串包含的字母相同,
// 因此对两个字符串分别进行排序之后得到的字符串一定是相同的,故可以将排序之后的字符串作为哈希表的键。
// 比如:"nat","tan",转为char以后,再sort,都得到ant,则赋值到map,它们就有相同的key;
// 再将"nat","tan"以value的形式对应相同的key插入map
// 最终返回map的value(list)即可

    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 = new LinkedList();
        list = map.getOrDefault(key, new ArrayList<String>());
        list.add(str);
        map.put(key,list);
    }
    return new ArrayList<List<String>>(map.values());
    }
}

注意:

1.char[] array = str.toCharArray()用的是toCharArray()方法

`toCharArray()` 是一个用于将字符串转换为字符数组的方法。

例如,如果 `str` 是 “Hello”,那么 `str.toCharArray()` 将返回一个包含字符 ‘H’, ‘e’, ‘l’, ‘l’, ‘o’ 的字符数组。

2. list = map.getOrDefault(key, new ArrayList<String>());

  • 如果 `map` 中存在 `key`,则将与 `key` 相关联的值赋给 `list`
  • 如果 `map` 中不存在 `key`,则将一个新的 `ArrayList<String>` 赋给 `list`

3. map.put(key,list);最后要记得把键值对加入map!

4.return new ArrayList<List<String>>(map.values());

`map.values()` 用于获取 `map` 中所有的值,并将这些值放入一个新的 `ArrayList` 中,然后作为返回值。

`map.values()` 返回的是一个 `Collection`,包含了 `map` 中所有的值。

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

// 暴力算法:我们考虑枚举数组中的每个数 x,考虑以其为起点,不断尝试匹配 x+1,x+2,⋯是否存在,假设最长匹配到了 x+y
// 那么以 x 为起点的最长连续序列即为 x,x+1,x+2,⋯ ,x+y,其长度为 y+1我们不断枚举并更新答案即可。
  
//优化思路: 由于我们要枚举的数 x一定是在数组中不存在前驱数 x−1 的,不然按照上面的分析我们会从 x−1 开始尝试匹配,
// 因此我们每次在哈希表中检查是否存在 x−1即能判断是否需要跳过了。

class Solution {
    public int longestConsecutive(int[] nums) {
    //set去重
    Set<Integer> set = new HashSet<Integer>();
    for (int num: nums){
        set.add(num);
    }
    int result  = 0;

    for (int num: set){       
        if (!set.contains(num-1)){
            int CurNum = num;
            int CurResult = 1;
            while(set.contains(CurNum+1)){
                CurResult +=1;
                CurNum +=1;
            }
        result = Math.max(result, CurResult);
        }
    }
    //变量 CurResult 在 for 循环内部定义,因此它在循环外部是不可见的。
    //return  Math.max(0, CurResult);

    return result;
    }
}

注意:

1.用set去重

2.set有contains方法,用来判断是否存在num-1和num+1

3.set的初始化:Set<Integer> set = new HashSet();

4.最后不能写return  Math.max(0, CurResult);

因为变量 CurResult 在 for 循环内部定义,它在循环外部是不可见的。

会报错:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值