哈希表篇

哈希表

有效的字母异位词

image-20241116112337412

/**
 * 242. 有效的字母异位词 字典解法
 * 时间复杂度O(m+n) 空间复杂度O(1)
 */
class Solution {
    public boolean isAnagram(String s, String t) {
        int[] record = new int[26];

        for (int i = 0; i < s.length(); i++) {
            record[s.charAt(i) - 'a']++;     // 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了
        }

        for (int i = 0; i < t.length(); i++) {
            record[t.charAt(i) - 'a']--;
        }
        
        for (int count: record) {
            if (count != 0) {               // record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。
                return false;
            }
        }
        return true;                        // record数组所有元素都为零0,说明字符串s和t是字母异位词
    }
}

注解:

这道题我在一开始做的时候没想到这种方法,当时想的可能是把字符按照从a到z排好,然后看最后两个字符串一样不一样。

两个数组的交集

image-20241116225637052

import java.util.HashSet;
import java.util.Set;

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0) {
            return new int[0];
        }
        Set<Integer> set1 = new HashSet<>();
        Set<Integer> resSet = new HashSet<>();
        //遍历数组1
        for (int i : nums1) {
            set1.add(i);
        }
        //遍历数组2的过程中判断哈希表中是否存在该元素
        for (int i : nums2) {
            if (set1.contains(i)) {
                resSet.add(i);
            }
        }
      
        //方法1:将结果集合转为数组
        
        ###mapToInt 是流的一个中间操作,它的作用是将流中的每个元素按照指定的函数进行映射转换,这里的函数是一个 Lambda 表达式 x -> x。
        对于 mapToInt 流,toArray() 方法最终会生成一个整数类型的数组,其元素就是原来集合 resSet 中经过转换后的整数元素。

        return resSet.stream().mapToInt(x -> x).toArray();
        
        //方法2:另外申请一个数组存放setRes中的元素,最后返回数组
        int[] arr = new int[resSet.size()];
        int j = 0;
        for(int i : resSet){
            arr[j++] = i;
        }
        
        return arr;
    }
}
我用的方法

import java.util.ArrayList;
class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        int[] cur1 = new int[1001];
        int[] cur2 = new int[1001];
        List<Integer> comp = new ArrayList<>();
        
        for (int i : nums1) {
            cur1[i] = 1;
        }
        for (int i : nums2) {
            cur2[i] = 1;
        }
        for (int i=0; i<=1000; i++) {
            if (cur1[i]==1 && cur2[i]==1) {
                comp.add(i);
            }
        }
        
      #############下面这个地方不是我想的,我自己这个地方没有解决#########  
        int index = 0;
        int res[] = new int[comp.size()];
        for (int i : comp) {
            res[index++] = i;
        }
        
        return res;
    }
}

快乐数

image-20241120160902253

看的答案解析

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

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

两数之和

image-20241120161056418

哈希表1,这个里面通过一遍循环,完成查找工作。

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int len = nums.length;
        int[] res = new int[2];
        if (nums == null || len == 0) {
            return res;
        }
        Map<Integer, Integer> map = new HashMap<>();
        for (int i=0; i<len; i++) {
            int temp = target - nums[i];
            if (map.containsKey(temp)) {
                res[1] = i;
                res[0] = map.get(temp);
                break;
            }
            map.put(nums[i], i);
        }
        return res;
    }
}
使用哈希表方法2

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> indexMap = new HashMap<>();
        
        for (int i=0; i<nums.length; i++) {
            int balance = target - nums[i];
            if (indexMap.containsKey(balance)) {
                return new int []{i, indexMap.get(balance)};
            } else {
                indexMap.put(nums[i], i);
            }
        }
    }
}
我自己写的

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

陌生-四数相加||

image-20241121151210269

官方代码

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        int res = 0;
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        //统计两个数组中的元素之和,同时统计出现的次数,放入map
        for (int i : nums1) {
            for (int j : nums2) {
                int sum = i + j;
                map.put(sum, map.getOrDefault(sum, 0) + 1);
            }
        }
        //统计剩余的两个元素的和,在map中找是否存在相加为0的情况,同时记录次数
        for (int i : nums3) {
            for (int j : nums4) {
                res += map.getOrDefault(0-i-j, 0);
            }
        }
        return res;
    }
}

了解-赎金信

image-20241121152859169

官方代码

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        if (ransomNote.length() > magazine.length()) return false;
        
        int[] record = new int[26];
        // toCharArray 主要作用是将一个String对象转换为一个字符数组
        for (char c : magazine.toCharArray()) {
            record[c - 'a'] += 1;
        }
        
        for (char c : ransomNote.toCharArray()) {
            record[c - 'a'] -= 1;
        }

        // 如果数组中存在负数,说明ransomNote字符串中存在magazine中没有的字符
        for (int i : record) {
            if (i < 0) {
                return false;
            }
        }
        
        return true;
    }
}

image-20241121152925434

陌生-多看-三数之和

image-20241121163934946

双指针法

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(nums);
        
        for (int i=0; i<nums.length; i++) {
            // 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了
            if (nums[i] > 0) {
                return result;
            }
            
            if (i>0 && nums[i]==nums[i-1]) {
                continue;
            }
            
            int left = i + 1;
            int right =nums.length - 1;
            while (right > left) {
                int sum = nums[i] + nums[left] + nums[right];
                if (sum > 0) {
                    right--;
                } else if (sum < 0) {
                    left++;
                } else {
                    result.add(Arrays.asList(nums[i], nums[left], nums[right]));
                    // 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
                    while (right > left && nums[right] == nums[right - 1]) right--;
                    while (right > left && nums[left] == nums[left + 1]) left++;
                    
                    right--;
                    left++;
                }
            }
        }
        return result;
    }
}

这个题解题思想要了解清楚。

// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
while (right > left && nums[right] == nums[right - 1]) right--;
while (right > left && nums[left] == nums[left + 1]) left++;

这个地方需要理清楚。

四数之和

image-20241121164241242

随想录给的代码:

public class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        Arrays.sort(nums);  // 排序数组
        List<List<Integer>> result = new ArrayList<>();  // 结果集
        for (int k = 0; k < nums.length; k++) {
            // 剪枝处理
            if (nums[k] > target && nums[k] >= 0) {
                break;
            }
            // 对nums[k]去重
            if (k > 0 && nums[k] == nums[k - 1]) {
                continue;
            }
            for (int i = k + 1; i < nums.length; i++) {
                // 第二级剪枝
                if (nums[k] + nums[i] > target && nums[k] + nums[i] >= 0) {
                    break;
                }
                // 对nums[i]去重
                if (i > k + 1 && nums[i] == nums[i - 1]) {
                    continue;
                }
                int left = i + 1;
                int right = nums.length - 1;
                while (right > left) {
                    long sum = (long) nums[k] + nums[i] + nums[left] + nums[right];
                    if (sum > target) {
                        right--;
                    } else if (sum < target) {
                        left++;
                    } else {
                        result.add(Arrays.asList(nums[k], nums[i], nums[left], nums[right]));
                        // 对nums[left]和nums[right]去重
                        while (right > left && nums[right] == nums[right - 1]) right--;
                        while (right > left && nums[left] == nums[left + 1]) left++;
                        right--;
                        left++;
                    }
                }
            }
        }
        return result;
    }

相当于在三数之和的基础上再套一层代码。

总结

posted @ 2024-11-28 18:33  墨羽寻觅  阅读(5)  评论(0编辑  收藏  举报