leetcode——哈希表

49. 字母异位词分组

题目

给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

示例:

输入: ["eat", "tea", "tan", "ate", "nat", "bat"]
输出:
[
  ["ate","eat","tea"],
  ["nat","tan"],
  ["bat"]
]
说明:

所有输入均为小写字母。
不考虑答案输出的顺序。

--------------------------------------------------------------------------------------------------

思路1

用哈希表来存储String, List<String>键值对:对于遍历到的每个字符串chArr,可以将它排好序后放入map中,之后只要判断map中是否有对应的String,若存在则取出对应的List,再将字符串放入;若不存在则新建一个list,将字符串放入新list后,再将(排好序的chArr,list)放入map中。

思路2

同样也是用哈希表,只不过表的key项是Integer:同时我们新建一个26个质数数组primes。对于遍历到的每个字符串chArr,将其字符对应的质数数组primes里的值相乘,如果字符串不相同,最后的乘积肯定也不相同。以此乘积作为key,这样就保证了唯一性。

思路2可能会出现溢出,即出现多个字符z。

 


347. 前 K 个高频元素

题目:给定一个非空的整数数组,返回其中出现频率前 k 高的元素。

示例 1:

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:

输入: nums = [1], k = 1
输出: [1]

--------------------------------------------------------------------------------------------------

思路

通过哈希表来记录元素与出现的次数,然后使用最大堆来存储元素,重写其比较规则为判断两数出现的次数。

    public int[] topKFrequent(int[] nums, int k) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for(int i = 0; i < nums.length; i++) {
           map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
        }
       PriorityQueue<Integer> maxHeap = new PriorityQueue<>(k, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                //若o2出现次数大于o1出现次数,返回1,小于则返回-1。
                return map.get(o1) - map.get(o2);
            }
       });
        
        for(int num : map.keySet()) {
            maxHeap.add(num);
            if(maxHeap.size() > k) {
              maxHeap.poll();
            }
        }
        int[] res = new int[k];
        for(int i = 0; i < k; i++) {
          res[i] = maxHeap.poll();
        }
        return res;
    }

复杂度分析

时间复杂度:O(N log(k))O(N log(k))。Counter 方法的复杂度是 O(N),建堆和输出的复杂度是 O(N log(k))。因此总复杂度为 O(N + N log(k)) = O(N log(k))。
空间复杂度:O(N),存储哈希表的开销。

 


560. 和为K的子数组

题目:给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。

示例 1 :

输入:nums = [1,1,1], k = 2
输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。

--------------------------------------------------------------------------------------------------

思路

(1)对于数组的某一区间[left, right],如果它们的和为k,可以说前right项的累加和 减去 前left项的累加和 等于k。

(2)因此我们可以在遍历数组元素nums[i]时,用哈希表map记录(i ,累加到当前元素的累加和sum出现的次数)。若累加和sum - k出现过,则加上它出现的次数。哈希表初始时记录了(0,1),以便在遍历数组时前left项出现累加和为k的情况

(3)以数组[3, 4, ,7, 2, -3, 1, 4, 2],k = 7为例:

          (0,1)
i = 0:(3,1)
i = 1:(7,1) cnt += (0, 1)
i = 2:(14,1) cnt+=(7, 1)
i = 3:(16,1)
i = 4:(13,1)
i = 5:(14,2)cnt+=(7, 1)
i = 6:(18,1)
i = 7:(20,1)cnt+=(13, 1)

    public int subarraySum(int[] nums, int k) {
      HashMap<Integer, Integer> map = new HashMap<>();
      map.put(0, 1);
      int len = nums.length, sum = 0, cnt = 0;

      for(int i = 0; i < len; i++) {
        sum += nums[i];
        if(map.containsKey(sum - k)) {
          cnt += map.get(sum - k);
        }
         map.put(sum, map.getOrDefault(sum, 0) + 1);
      }
      return cnt; 
    }

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值