有关哈希表练习题整理

1、两数之和

思路:使用哈希表,将值作为key,下标作为value存入,因为是两数之和,所以另一个数一定是目标-某个数,如果另一个数在哈希表里即可返回下标。

    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer,Integer> hashMap = new HashMap();

        for(int i = 0 ; i < nums.length ; i++){
            int other = target - nums[i];
            if(hashMap.containsKey(other)){
                return new int[]{hashMap.get(other), i};
            }
            //值作为哈希key 下标作为value
            hashMap.put(nums[i],i);
        }
        return new int[0];
    }

2、只出现一次的数字

 思路一:使用哈希表将每个数字出现的次数作为value,数字为key存入哈希表,再次循环哈希表,判断如果频率为1则找出

    public static int singleNumber(int[] nums) {
        HashMap<Integer,Integer> hashMap = new HashMap<>();
        for(int i = 0 ; i < nums.length ; i++){
            if(hashMap.containsKey(nums[i])){
                Integer count = hashMap.get(nums[i]);
                hashMap.put(nums[i],++count);
            }else{
                hashMap.put(nums[i],1);
            }
        }
        for (Integer key : hashMap.keySet()) {
            if(hashMap.get(key)==1){
                return key;
            }
        }
        return 0;
    }

思路二:抑或运算

1、因为任意数和0进行异或运算都等于其自身

2、任意数和自己做抑或都为零

3、最后剩下的那个数肯定和0进行抑或等于自身

class Solution {
    public int singleNumber(int[] nums) {
        int single = 0;
        for(int num : nums){
           single ^= num;
        }
        return single;
    }
}

3、前K个高频元素

 思路一:将数字和频率作为key和value存入哈希表,再次循环做一个下标为频率的list哈希表,list存入对应频率的数字,下标>=k的数字即是答案

    public static int[] topKFrequent(int[] nums, int k) {
        ArrayList<Integer> restList = new ArrayList<>();
        HashMap<Integer,Integer> hashMap = new HashMap<>();
        int max = 1;
        for(int num : nums){
            if(hashMap.containsKey(num)){
                Integer count = hashMap.get(num);
                max = count+1 > max ? count+1 : max; //最高频率做下面数组的size
                hashMap.put(num,++count);
            }else{
                hashMap.put(num,1);
            }
        }
        List<Integer>[] list = new List[max+1];
        for (Integer key : hashMap.keySet()) {
            int index = hashMap.get(key);
            if(list[index] == null){
                list[index] = new ArrayList<>();
            }
            list[index].add(key);
        }
        for(int i = list.length-1 ; i >= k; i--){
            List<Integer> integers = list[i];
            if(integers != null){
                for(int num : integers){
                    restList.add(num);
                }
            }

        }
        int[] resArr = new int[restList.size()];
        for(int i = 0 ; i < resArr.length ; i++){
            resArr[i] = restList.get(i);
        }
        return resArr;
    }

思路二:以数字-频率为key和value做哈希表,在利用小顶堆,根据频率大小存入数字,因为是队列二叉树,频率最小的数字会放在根节点,每次存入的时候先和根节点进行比较再决定放不放入。

因为k 的取值范围是 [1, 数组中不相同的元素的个数],所以小顶堆的最大容量就是k,根据频率放入的数量就是要求的k

    public static int[] topKFrequent2(int[] nums, int k) {
        HashMap<Integer,Integer> hashMap = new HashMap<>();
        for(int num : nums){
            if(hashMap.containsKey(num)){
                Integer count = hashMap.get(num);
                hashMap.put(num,++count);
            }else{
                hashMap.put(num,1);
            }
        }

        //小顶堆
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                //频率小的往上放
                return hashMap.get(o1) - hashMap.get(o2);
            }
        });
        for (Integer key : hashMap.keySet()) {
            if(priorityQueue.size() < k){
                priorityQueue.offer(key);
                //对比根节点的频率大小决定是否放入
            }else if(hashMap.get(key) > hashMap.get(priorityQueue.peek())){
                priorityQueue.poll();
                priorityQueue.offer(key);
            }
        }
        int [] res = new int [k];
        int ind = 0;
        while(!priorityQueue.isEmpty()){
            res[ind++] = priorityQueue.poll();
        }

        return res;
    }

4、无重复字符的最长字符串

 思路一:用哈希表来确定是否重复字符,记录下标,字符串长度等于重复的下标-最开始的下标,最开始的下标用滑动窗口确定

    public static int lengthOfLongestSubstring(String s) {
        HashMap<Character,Integer> hashMap = new HashMap<>();
        int max = 0;
        int left = 0;
        //abcaa
        for(int i = 0 ; i <s.length(); i++){
            if(hashMap.containsKey(s.charAt(i))){
                //为什么要加max,因为abba这样 a重复的时候不能回到一开始
                left = Math.max(left,hashMap.get(s.charAt(i))+1);
            }
            hashMap.put(s.charAt(i),i);
            max = Math.max(max,i-left+1);
        }
        return max;
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值