数据结构-哈西表笔记

自定义26位字母哈西表

有效的字母异位词

242. 有效的字母异位词 - 力扣(LeetCode)

java 复制代码
class Solution {
    public boolean isAnagram(String s, String t) {

        // 获取字符串 s 和 t 的长度
        int sLen = s.length();
        int tLen = t.length();

        // 如果两个字符串的长度不相等,则它们不可能是字母异位词
        if (sLen != tLen) {
            return false;
        }

        // 创建一个大小为 26 的数组 count 来统计每个字母出现的次数
        // 数组的索引 0-25 对应字母 'a'-'z'
        int count[] = new int[26];

        // 遍历字符串 s,并更新 count 数组
        // 对于 s 中的每个字符,计算其相对于 'a' 的索引位置,并将该位置的计数器加 1
        for (int i = 0; i < sLen; i++) {
            count[s.charAt(i) - 'a']++;
        }

        // 遍历字符串 t,检查每个字符在 count 数组中的计数
        for (int i = 0; i < tLen; i++) {
            // 如果 t 中的某个字符的计数已经为 0 或小于 0,说明它在 s 中不存在
            // 或者 s 中该字符出现的次数不足,直接返回 false
            if (count[t.charAt(i) - 'a'] <= 0) {
                return false;
            }
            // 对于 t 中的每个字符,计算其索引位置,并将该位置的计数器减 1
            count[t.charAt(i) - 'a']--;
        }

        // 如果所有字符的出现次数都能相互抵消,说明 s 和 t 是字母异位词
        return true;
    }
}

赎金信

383. 赎金信 - 力扣(LeetCode)

java 复制代码
class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        
        // 不需要检查长度是否相等,题目并未要求
        int[] map = new int[26]; // 长度为26的数组,用于记录字符次数

        // 遍历 `magazine`,将每个字符出现的次数记录到 `map` 中。
        for(int i = 0; i < magazine.length(); i++){
            map[magazine.charAt(i) - 'a']++;  // 累加 magazine 中字符的出现次数
        }

        // 遍历 `ransomNote`,减少对应字符的计数。
        for(int i = 0; i < ransomNote.length(); i++){
            map[ransomNote.charAt(i) - 'a']--; // 减少 ransomNote 中字符的计数
            // 如果某个字符在 `magazine` 中的数量不足以构造 `ransomNote`,返回 false
            if(map[ransomNote.charAt(i) - 'a'] < 0){
                return false;
            }
        }

        return true; // 能够成功构造则返回 true
    }
}

java自带hashset

两个数组的交集

349. 两个数组的交集 - 力扣(LeetCode)

java 复制代码
class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {

        // 创建一个 HashSet 存储 nums1 中的所有元素,避免重复
        Set<Integer> hashset1 = new HashSet<>();
        // 创建另一个 HashSet 存储 nums2 中与 nums1 交集的元素
        Set<Integer> hashset2 = new HashSet<>();

        // 遍历 nums1 数组,并将其所有元素添加到 hashset1 中
        for (int i = 0; i < nums1.length; i++) {
            hashset1.add(nums1[i]);  // HashSet 自动去重
        }

        // 遍历 nums2 数组,检查 hashset1 是否包含 nums2 中的元素
        // 如果包含,则该元素为交集,将其添加到 hashset2 中
        for (int i = 0; i < nums2.length; i++) {
            if (hashset1.contains(nums2[i])) {
                hashset2.add(nums2[i]);  // 只添加交集部分的元素
            }
        }

        // 将 hashset2 中的元素转换为数组形式,返回交集结果
        int ret[] = new int[hashset2.size()];  // 初始化结果数组,大小为交集元素的个数
        int i = 0;
        for (int temp : hashset2) {
            ret[i] = temp;  // 将 HashSet 中的元素逐一存入数组
            i++;
        }

        return ret;  // 返回最终的交集数组
    }
}

快乐数

202. 快乐数 - 力扣(LeetCode)

java 复制代码
class Solution {
    public boolean isHappy(int n) {

        // 创建一个 HashSet 来记录已经计算过的数字,防止进入无限循环
        Set<Integer> hashset = new HashSet<>();

        // 循环条件:n 不等于 1 且 n 不在 hashset 中时继续循环
        while (n != 1 && !hashset.contains(n)) {
            // 将当前数字 n 加入 hashset,表示已经访问过
            hashset.add(n);
            // 计算 n 的各位数字的平方和,更新 n
            n = isHappySum(n);
        }

        // 如果最终 n 等于 1,则返回 true,表示该数字是快乐数;否则返回 false
        return n == 1;
    }

    // 计算数字 n 的各位数字平方和的函数
    int isHappySum(int n) {
        int sum = 0;
        // 当 n > 0 时,不断取出各位数字并计算它们的平方
        while (n > 0) {
            int temp = n % 10;  // 取出 n 的最后一位数字
            sum += temp * temp;  // 计算该位数字的平方并累加到 sum
            n /= 10;  // 去掉最后一位数字
        }
        // 返回各位数字平方和
        return sum;
    }
}

哈希表HashMap

两数之和

1. 两数之和 - 力扣(LeetCode)

java 复制代码
import java.util.HashMap;

class Solution {
    public int[] twoSum(int[] nums, int target) {
        // 创建一个长度为2的数组,用于存放结果
        int ret[] = new int[2];

        // 创建一个哈希表,用于存储数组元素及其对应的索引
        HashMap<Integer, Integer> map = new HashMap<>();

        // 遍历输入数组,将每个元素及其索引存入哈希表
        for (int i = 0; i < nums.length; i++) {
            map.put(nums[i], i);
        }

        // 再次遍历输入数组,寻找两个数的和等于目标值
        for (int i = 0; i < nums.length; i++) {
            // 计算当前元素所需的另一半
            int temp = target - nums[i];

            // 检查哈希表中是否存在另一半,且它的索引不是当前元素的索引
            if (map.containsKey(temp) && map.get(temp) != i) {
                // 找到满足条件的两个元素,存入结果数组
                ret[0] = i;               // 当前元素的索引
                ret[1] = map.get(temp);  // 另一半的索引
                break;                   // 找到结果后跳出循环
            }
        }

        return ret; // 返回结果数组
    }
}

四数相加II

454. 四数相加 II - 力扣(LeetCode)

java 复制代码
class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        // 创建一个 HashMap 用于存储 nums1 和 nums2 的所有可能和及其出现的次数
        HashMap<Integer, Integer> map = new HashMap<>();
        int ret = 0; // 用于存储符合条件的四元组数量

        // 遍历 nums1 和 nums2 以计算所有可能的和
        for (int i = 0; i < nums1.length; i++) {
            for (int j = 0; j < nums2.length; j++) {
                // 计算 nums1[i] 和 nums2[j] 的和
                int temp = nums1[i] + nums2[j];
                // 如果 map 中已经存在该和,则将其计数加一
                if (map.containsKey(temp)) {
                    map.put(temp, map.get(temp) + 1);
                } else {
                    // 否则,将该和加入 map,并初始化计数为 1
                    map.put(temp, 1);
                }
            }
        }

        // 遍历 nums3 和 nums4 以查找与 map 中的和匹配的元素
        for (int i = 0; i < nums3.length; i++) {
            for (int j = 0; j < nums4.length; j++) {
                // 计算 - (nums3[i] + nums4[j]),以便与 map 中的和进行匹配
                int temp = -nums3[i] - nums4[j];
                // 如果 map 中存在这个和,则将该和对应的计数加到 ret 中
                if (map.containsKey(temp)) {
                    ret += map.get(temp);
                }
            }
        }

        // 返回符合条件的四元组的总数
        return ret;
    }
}

双指针

三数之和(难)

难在去重。如果不用去重就可以用哈希表

15. 三数之和 - 力扣(LeetCode)

java 复制代码
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        // 初始化结果列表,用来存储所有符合条件的三元组
        List<List<Integer>> ret = new ArrayList<>();

        // 首先对输入数组进行排序,这样我们可以利用排序后的性质来避免重复和进行双指针操作
        Arrays.sort(nums);

        // 遍历排序后的数组,i 是第一个选定的数,遍历数组中所有可能的第一个数
        for (int i = 0; i < nums.length; i++) {
            // 如果当前数大于0,则没有必要继续查找,因为在排序数组中,后续的数也都大于0,三数之和不可能为0
            if (nums[i] > 0) {
                break;
            }

            // 跳过重复的数值,避免结果中出现重复的三元组
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }

            // 设置双指针,left 指向当前数之后的元素,right 指向数组末尾
            int left = i + 1;
            int right = nums.length - 1;

            // 使用双指针方法寻找三个数的和为0的组合
            while (left < right) {
                // 计算当前三个数的和
                int sum = nums[i] + nums[left] + nums[right];

                // 如果和大于0,说明右指针处的数太大,需要左移右指针
                if (sum > 0) {
                    right--;
                // 如果和小于0,说明左指针处的数太小,需要右移左指针
                } else if (sum < 0) {
                    left++;
                // 如果和等于0,找到了一个符合条件的三元组
                } else {
                    // 将找到的三元组加入结果列表
                    ret.add(Arrays.asList(nums[i], nums[left], nums[right]));

                    // 为了避免重复的三元组,继续移动左指针,跳过所有重复的左边元素
                    while (left < right && nums[left] == nums[left + 1]) {
                        left++;
                    }

                    // 同样,继续移动右指针,跳过所有重复的右边元素
                    while (left < right && nums[right] == nums[right - 1]) {
                        right--;
                    }

                    // 在找到一个三元组后,继续尝试其他可能性,因此移动双指针
                    left++;
                    right--;
                }
            }
        }
        // 返回所有找到的不重复的三元组
        return ret;
    }
}

四数之和(难)

. - 力扣(LeetCode)

java 复制代码
class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        // 这个列表将存储最终的四元组结果
        List<List<Integer>> ret = new ArrayList<>();
        
        // 排序输入数组,以便于避免重复并使用双指针技术
        Arrays.sort(nums);

        // 遍历数组,选择四元组中的第一个数字
        for (int i = 0; i < nums.length; i++) {
            // 如果当前数字大于目标值且非负,可以提前结束
            if (nums[i] > target && nums[i] >= 0) {
                break;
            }
            
            // 跳过第一个数字的重复项
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }

            // 遍历选择第二个数字
            for (int j = i + 1; j < nums.length; j++) {
                // 检查前两个数字的和是否已经超过目标值
                if (nums[i] + nums[j] > target && nums[i] + nums[j] >= 0) {
                    break;
                }

                // 跳过第二个数字的重复项
                if (j > i + 1 && nums[j] == nums[j - 1]) {
                    continue;
                }

                // 设置两个指针以查找剩下的两个数字
                int left = j + 1;
                int right = nums.length - 1;

                // 使用双指针查找剩下的两个数字
                while (left < right) {
                    // 计算四个数字的和
                    int sum = nums[i] + nums[j] + nums[left] + nums[right];

                    // 如果和小于目标值,移动左指针向右
                    if (sum < target) {
                        left++;
                    }
                    // 如果和大于目标值,移动右指针向左
                    else if (sum > target) {
                        right--;
                    }
                    // 如果和等于目标值,找到一个四元组
                    else {
                        // 将四元组添加到结果列表
                        ret.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));

                        // 跳过第三个数字的重复项
                        while (left < right && nums[left] == nums[left + 1]) {
                            left++;
                        }
                        // 跳过第四个数字的重复项
                        while (left < right && nums[right] == nums[right - 1]) {
                            right--;
                        }
                        // 找到有效的四元组后,移动两个指针
                        left++;
                        right--;
                    }
                }
            }
        }
        // 返回唯一四元组的列表
        return ret;
    }
}
相关推荐
懒惰的bit9 天前
STM32F103C8T6 学习笔记摘要(四)
笔记·stm32·学习
zkyqss9 天前
OVS Faucet练习(下)
linux·笔记·openstack
浦东新村轱天乐10 天前
【麻省理工】《how to speaking》笔记
笔记
奔跑的蜗牛AZ10 天前
TiDB 字符串行转列与 JSON 数据查询优化知识笔记
笔记·json·tidb
cwtlw10 天前
Excel学习03
笔记·学习·其他·excel
杭州杭州杭州10 天前
计算机网络笔记
笔记·计算机网络
cyborg10 天前
终于再也不用在notion中写公式了
笔记
循环过三天10 天前
1.2、CAN总线帧格式
笔记·stm32·单片机·嵌入式硬件·学习
循环过三天10 天前
1.1、CAN总线简介
笔记·stm32·单片机·嵌入式硬件·学习
mooyuan天天10 天前
pikachu靶场通关笔记43 SSRF关卡01-CURL(三种方法渗透)
笔记·安全·web安全·ssrf漏洞