LeetCode哈希表相关解法

1. 理论

哈希碰撞的解决方法

拉链法

冲突采用链表的方式剞劂

哈希表4

线性探测法

放入元素的时候,如果碰撞了,就往后找一个空位放该元素

要求tableSize一定要大于dataSize ,要不然哈希表上就没有空置的位置来存放冲突的数据了

img

2. 有效的字母异位词

242. 有效的字母异位词

先遍历一遍第一个字符串,把每个字符放入Map中,重复则个数+1
然后遍历第二个,遇上就个数-1,如果是字母异位词的话,最终每个字母的个数一定为0

class Solution {
    public boolean isAnagram(String s, String t) {
        if(s.length() != t.length()){
            return false;
        }
        Map<Character, Integer> map = new HashMap<>();
        char[] arr1 = s.toCharArray();
        char[] arr2 = t.toCharArray();

        for(int i = 0; i < arr1.length; i++){
            if(map.containsKey(arr1[i])){
                map.put(arr1[i], map.get(arr1[i]) + 1);
            }else{
                map.put(arr1[i], 1);
            }
        }

        for(int i = 0; i < arr2.length; i++){
            if(map.containsKey(arr2[i])){
                if(map.get(arr2[i]) == 0){
                    return false;
                }
                map.put(arr2[i], map.get(arr2[i]) - 1);
            }else{
                return false;
            }
        }
        return true;
      

    }
}

追求更快的话,可以使用长度为26的数组,然后也是差不多的思想,一个遇上就+1,第二个遇上减1

242.有效的字母异位词

3. 两个数组的交集

349. 两个数组的交集

  1. 先遍历第一个数组,存入map中,每个字符的个数为1
  2. 遍历第二个数组,如果map中有当前数字,并且为第一次出现,说明是交集
  3. 如何遍历map,找到出现次数为2的数字,放入数组(采用ArrayList,包装类会报错)
class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Map<Integer, Integer> map = new HashMap<>();
        int sameNums = 0;

        for(int i = 0; i < nums1.length; i++){
            if(!map.containsKey(nums1[i])){
                map.put(nums1[i], 1);
            }
        }

        
        for(int i = 0; i < nums2.length; i++){
            if(map.containsKey(nums2[i]) && map.get(nums2[i]) == 1){
                map.put(nums2[i], 2);
                sameNums++;
            }
        }

        int[] res = new int[sameNums];
        int index = 0;

        for(Integer i: map.keySet()){
            if(map.get(i) == 2){
                res[index] = i;
                index++;
            }
        }

        return res;
    }
}

4. 快乐数

202. 快乐数

用一个Set存储出现过的数字,如果一个数字经过变化后再次变为了原来的数字,那他肯定不是快乐数

class Solution {
    public boolean isHappy(int n) {
        Set<Integer> set = new HashSet<>();
		
        while(n != 1 && !set.contains(n)){
            set.add(n);
            n = getNextNumber(n);
        }

        return n == 1;
    }

    private int getNextNumber(int n) {
        int sum = 0;
        while(n > 0){
            int tail = n % 10;
            sum += tail * tail;
            n /= 10;
        }
        return sum;
    }
}

5.两数之和

  1. 因为题目要找的两个数之和为target,我们可以把nums数组中第一个元素的target - num 以及 num的下标分别放入 HashMap<Integer,Integer>的Key 和 Value中
  2. 按照这种方法遍历数组,进行判断,如果有元素和HashMap中的Key值相等的话,那么他们的和为target
  3. 输出结果
class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();
         //放入第一个数,K中为差,V中为下标
        map.put(target - nums[0],0);
        for (int i = 1; i < nums.length; i++) {
            //如果该元素和HashMap中的某个Key值相等的话,结束
            if(map.containsKey(nums[i])){
                int index = map.get(nums[i]);
                return new int[]{index,i};
            }else {
                //放入HashMap
                map.put(target - nums[i],i);
            }
        }
        return new int[0];
    }
}

6. 赎金信

383. 赎金信

类似字母异位词

  1. 第一个数组全放入map,如果相等就次数+1
  2. 第二个数组如果遇到对应的字符,就次数-1
  3. 如果最终map中次数都<=0 那么可以完成
class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        if(ransomNote.length() > magazine.length()){
            return false;
        }

        Map<Character, Integer> map = new HashMap<>();
        char[] arr1 = ransomNote.toCharArray();
        char[] arr2 = magazine.toCharArray();

        for(int i = 0; i < arr1.length; i++){
            if(map.containsKey(arr1[i])){
                map.put(arr1[i], map.get(arr1[i]) + 1);
            }else{
                map.put(arr1[i], 1);
            }
        }

        for(int i = 0; i < arr2.length; i++){
            //如果存在,个数-1
            if(map.containsKey(arr2[i])){
                map.put(arr2[i], map.get(arr2[i]) - 1);
            }
        }

        for(Character c: map.keySet()){
            if(map.get(c) > 0){
                return false;
            }
        }
        
        return true;
    }
}

7. 三数之和

15. 三数之和

这题用哈希法很麻烦

双指针法

15.三数之和

  1. 先进行排序
  2. i 遍历 数组, left从i+1开始,right从 n-1开始, left 和 right向中间移动,这个过程可能发现多组,可能有重复
  3. 如果 nums[i] == nums[i - 1] 当前和上一个相同则重复了(i left right 都要进行重复的判断)
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);

        List<List<Integer>> list = new ArrayList<>();

        for (int i = 0; i < nums.length; i++) {
            //开头>0,不可能等于0
            if (nums[i] > 0) {
                return list;
            }

            // 去重i 和上一个(左边)的比较
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }

            int left = i + 1;
            int right = nums.length - 1;
            while (left < right) {
                int sum = nums[i] + nums[left] + nums[right];
                if (sum < 0) {
                    left++;
                } else if (sum > 0) {
                    right--;
                } else {
                    list.add(Arrays.asList(nums[i], nums[left], nums[right]));
                    //去重left 和下一个(左边)的比较
                    while (right > left && nums[right] == nums[right - 1]) right--;
                    //去重right 和下一个(右边)的比较
                    while (right > left && nums[left] == nums[left + 1]) left++;
                    left++;
                    right--;
                }
            }
        }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值