01:哈希-启动!

两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。

class Solution{
  public int[] two_sum(int[] nums,int target){
    Map<Integer,Integer> map = new HashMap<>();
    for(int i=0;i<nums.length,++i){
      diff = target - nums[i];
      if(map.containKey(diff)) {
        return new int[]{i,map.get(diff)}
      }
      map.put(nums[i],i);
    }
    return null;
  }  
}

字母异位词分组

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

  • 方法1
    异位词按照字母顺序做排序后一定相等,所以对每一个词利用Array.sort进行排序,结果作为key,value为一个列表,存放排序后为当前key的所有词
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, List<String>> map = new HashMap<>();
        for (String str : strs) {
            char[] chars = str.toCharArray();
            Arrays.sort(chars);
            String sort_str = new String(chars);
            if(map.containsKey(sort_str)){
                map.get(sort_str).add(str);
            }else{
                List list = new ArrayList<>();
                list.add(str);
                map.put(sort_str,list);
            }
        }
        return new ArrayList<>(map.values());
    }
}
  • 方法2
    字母异位词的原料一定相同,所以可以利用一个类来描述该词,即利用一个数组来存储该词的每一个字母的个数。该类可以替代方法1的key。
    注意:一定要要重写equals和hashcode方法!
    此方法无需对字符串进行排序,而是遍历累加,所以时间复杂度上会更优秀。
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<Word, List<String>> map = new HashMap<>();
        for (String str : strs) {
            Word word = new Word(str);
            if(map.containsKey(word)){
                map.get(word).add(str);
            }else{
                List list = new ArrayList<>();
                list.add(str);
                map.put(word,list);
            }
        }
        return new ArrayList<>(map.values());
    }
    class Word{
        private char[] chars = new char[26];
        Word(String s){
            char[] chars1 = s.toCharArray();
            for (char c: chars1) {
                chars[c-'a']++;
            }
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Word word = (Word) o;
            return Arrays.equals(chars, word.chars);
        }

        @Override
        public int hashCode() {
            return Arrays.hashCode(chars);
        }
    }
}

#最长连续序列
给定一个未排序的整数数组 nums(数据可重复)找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) 的算法解决此问题。
方法:将所有元素都放进哈希表中,key是唯一标识即可(所以用hashset即可),value即为元素值,然后遍历该哈希表,假如当前遍历值为v,若哈希表中不存在v-1,则证明它是连续序列的开头,则从它开始循环查找是否存在v+1,v+2…,若存在则将当前的序列长度+1,否则跳出循环,继续遍历哈希表。

class Solution {
    public int longestConsecutive(int[] nums) {
        HashSet<Integer> hashset = new HashSet<>();
        for (int i = 0; i < nums.length; i++) {
            hashset.add(nums[i]);
        }
        int count = 0;
        int res = 0;
        for (int v: hashset) {
            if(!hashset.contains(v-1)){
                count = 1;
                int current = v;
                while(hashset.contains(current+1)){
                    count++;
                    current++;
                }
                res = Math.max(count,res);
            }
            
        }
        return res;
    }
}

总结

哈希表主要利用空间换时间的思想
在题目中也要注意数据规模的提示# 两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。

class Solution{
  public int[] two_sum(int[] nums,int target){
    Map<Integer,Integer> map = new HashMap<>();
    for(int i=0;i<nums.length,++i){
      diff = target - nums[i];
      if(map.containKey(diff)) {
        return new int[]{i,map.get(diff)}
      }
      map.put(nums[i],i);
    }
    return null;
  }  
}

字母异位词分组

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

  • 方法1
    异位词按照字母顺序做排序后一定相等,所以对每一个词利用Array.sort进行排序,结果作为key,value为一个列表,存放排序后为当前key的所有词
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, List<String>> map = new HashMap<>();
        for (String str : strs) {
            char[] chars = str.toCharArray();
            Arrays.sort(chars);
            String sort_str = new String(chars);
            if(map.containsKey(sort_str)){
                map.get(sort_str).add(str);
            }else{
                List list = new ArrayList<>();
                list.add(str);
                map.put(sort_str,list);
            }
        }
        return new ArrayList<>(map.values());
    }
}
  • 方法2
    字母异位词的原料一定相同,所以可以利用一个类来描述该词,即利用一个数组来存储该词的每一个字母的个数。该类可以替代方法1的key。
    注意:一定要要重写equals和hashcode方法!
    此方法无需对字符串进行排序,而是遍历累加,所以时间复杂度上会更优秀。
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<Word, List<String>> map = new HashMap<>();
        for (String str : strs) {
            Word word = new Word(str);
            if(map.containsKey(word)){
                map.get(word).add(str);
            }else{
                List list = new ArrayList<>();
                list.add(str);
                map.put(word,list);
            }
        }
        return new ArrayList<>(map.values());
    }
    class Word{
        private char[] chars = new char[26];
        Word(String s){
            char[] chars1 = s.toCharArray();
            for (char c: chars1) {
                chars[c-'a']++;
            }
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Word word = (Word) o;
            return Arrays.equals(chars, word.chars);
        }

        @Override
        public int hashCode() {
            return Arrays.hashCode(chars);
        }
    }
}

#最长连续序列
给定一个未排序的整数数组 nums(数据可重复)找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) 的算法解决此问题。
方法:将所有元素都放进哈希表中,key是唯一标识即可(所以用hashset即可),value即为元素值,然后遍历该哈希表,假如当前遍历值为v,若哈希表中不存在v-1,则证明它是连续序列的开头,则从它开始循环查找是否存在v+1,v+2…,若存在则将当前的序列长度+1,否则跳出循环,继续遍历哈希表。

class Solution {
    public int longestConsecutive(int[] nums) {
        HashSet<Integer> hashset = new HashSet<>();
        for (int i = 0; i < nums.length; i++) {
            hashset.add(nums[i]);
        }
        int count = 0;
        int res = 0;
        for (int v: hashset) {
            if(!hashset.contains(v-1)){
                count = 1;
                int current = v;
                while(hashset.contains(current+1)){
                    count++;
                    current++;
                }
                res = Math.max(count,res);
            }
            
        }
        return res;
    }
}

总结

哈希表主要利用空间换时间的思想
在题目中也要注意数据规模的提示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值