代码随想录算法训练营第6天 | 哈希表理论基础,242.有效的字母异位词,349. 两个数组的交集,202. 快乐数,1. 两数之和

242.有效的字母异位词

题目链接:LeetCode
文章讲解:代码随想录
视频讲解:哔哩哔哩
编写语言:Java
完成状态:已完成

解题思路

  • 将26个字母存放到数组中,两个数组进行遍历计数,再进行比较或者用一个数组也可,只需进行相应的减法
  • 使用双重循环进行逐一清除判断,最后字符串长度为0则匹配成功

代码

  1. 数组
class Solution {
    public boolean isAnagram(String s, String t) {
        if (s.length() != t.length()) { // 如果两个字符串的长度不相等,说明它们不可能是字母异位词
            return false;
        }

        int[] a = new int[200]; // 创建一个大小为200的整型数组,用来统计每个字符出现的次数

        // 遍历字符串s,统计每个字符出现的次数
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            a[ch]++; // 字符ch对应的数组元素值加1
        }

        // 遍历字符串t,将每个字符出现的次数减1
        for (int i = 0; i < t.length(); i++) {
            char ch = t.charAt(i);
            a[ch]--; // 字符ch对应的数组元素值减1
        }

        // 检查数组中是否有非零元素,如果有则说明两个字符串的字符数量不匹配,不是字母异位词
        for (int i = 97; i <= 122; i++) { // 字母a-z对应ASCII码值为97-122
            if (a[i] != 0) {
                return false;
            }
        }

        return true; // 数组中所有元素都为零,说明两个字符串是字母异位词

    }
}
  1. List集合
class Solution {
    public boolean isAnagram(String s, String t) {
        if (s.length() != t.length()) { // 如果字符串s和t的长度不相等,返回false
            return false;
        }

        List<Character> list = new ArrayList<>(); // 创建一个字符列表list

        for (int i = 0; i < s.length(); i++) { // 将字符串s中的每个字符添加到列表中
            char ch = s.charAt(i);
            list.add(ch);
        }

        for (int i = 0; i < t.length(); i++) { // 遍历字符串t中的每个字符
            char ch = t.charAt(i);
            boolean flag = list.remove(Character.valueOf(ch)); // 尝试从列表中删除当前字符ch
            if (!flag) { // 如果删除失败(即列表中不存在该字符),则t不是s的字谜,返回false
            	return false;
            }
        }

        return true; // 如果所有字符都被成功删除,说明t是s的字谜,返回true
    }
}
  1. Map集合
class Solution {
    public boolean isAnagram(String s, String t) {
        if (s.length() != t.length()) { // 如果两个字符串的长度不相等,则它们一定不是异位词
            return false;
        }

        Map<Character, Integer> map = new HashMap<>(); // 创建一个用于存储字符频率的映射表

        for (int i = 0; i < s.length(); i++) {
        	char c = s.charAt(i); // 获取第i个字符
            if (map.containsKey(c)) { // 如果映射表中已经包含该字符,则将其频率加1
                map.put(c, map.get(c) + 1);
            } else { // 否则将该字符加入映射表,并将其频率初始化为1
                map.put(c, 1);
            }
        }

        for (int i = 0; i < t.length(); i++) {
        	char c = t.charAt(i); // 获取第i个字符
            if (map.containsKey(c)) { // 如果映射表中包含该字符
                map.put(c, map.get(c) - 1); // 将其频率减1
                if (map.get(c) == 0) { // 如果频率变为0,则从映射表中移除该字符
                    map.remove(c);
                }
            } else { // 如果映射表中不包含该字符,则说明两个字符串不是异位词
                return false;
            }
        }

        return true; // 如果遍历完t字符串后,映射表为空,则说明两个字符串是异位词
    }
}

349. 两个数组的交集

题目链接:LeetCode
文章讲解:代码随想录
视频讲解:哔哩哔哩
编写语言:Java
完成状态:已完成

解题思路

  • 设置哈希表用set直接去重 当数据比较小时(此题为1000),可以考虑数组的方式

代码

  1. 数组
class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        // 创建一个存放结果的集合
        Set<Integer> set_result = new HashSet<>();
        
        // 创建一个用于标记数字是否在第一个数组中出现的数组
        int[] num_result = new int[1010];
        
        // 遍历第一个数组,将数字存入num_result数组中,并标记为出现过
        for (int i = 0; i < nums1.length; i++) {
            num_result[nums1[i]] = 1;
        }

        // 遍历第二个数组,如果数字在num_result中被标记为出现过,就加入结果集合中
        for (int i = 0; i < nums2.length; i++) {
            if (num_result[nums2[i]] == 1) {
                set_result.add(nums2[i]);
            }
        }

        // 将结果集合转换为整型数组
        Integer[] num_result1 = set_result.toArray(new Integer[set_result.size()]);
        int[] num_result2 = new int[num_result1.length];
        for (int i = 0; i < num_result2.length; i++) {
            num_result2[i] = num_result1[i];
        }

        return num_result2;
    }
}
  1. Set集合
class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> set_result = new HashSet<>(); // 创建一个HashSet用于存储结果集
        Set<Integer> set1 = new HashSet<>(); // 创建一个HashSet用于存储nums1中的元素

        for (int i = 0; i < nums1.length; i++) { // 遍历nums1数组
            set1.add(nums1[i]); // 将nums1中的元素添加到set1中
        }

        for (int i = 0; i < nums2.length; i++) { // 遍历nums2数组
            if (set1.contains(nums2[i])) { // 如果set1中包含nums2[i],则将nums2[i]加入结果集set_result中
                set_result.add(nums2[i]);
            }
        }

        Integer[] num_result1 = set_result.toArray(new Integer[0]); // 将结果集转换为Integer数组
        int[] num_result2 = new int[num_result1.length]; // 创建一个和结果集长度相同的int数组

        for (int i = 0; i < num_result2.length; i++) { // 将Integer数组转换为int数组
            num_result2[i] = num_result1[i];
        }

        return num_result2; // 返回结果集
    }
}

202. 快乐数

题目链接:LeetCode
文章讲解:代码随想录
编写语言:Java
完成状态:已完成

解题思路

  • 题目中说了会 无限循环,那么也就是说求和的过程中,sum会重复出现,这对解题很重要!
  • 所以这道题目使用哈希法,来判断这个sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止。

代码

  1. Set集合
class Solution {
    public boolean isHappy(int n) {
        Set<Integer> set = new HashSet<>();  // 创建一个用于存储出现过的数字的集合
        while (true) {
            int sum = getSum(n);  // 计算n的每位数字的平方和
            if (sum == 1) {  // 如果平方和为1,则n是快乐数
                return true;
            }

            if (set.contains(sum)) {  // 如果平方和已经出现过,说明进入了循环,n不是快乐数
                return false;
            } else {
                set.add(sum);  // 将平方和添加到集合中
            }

            n = sum;  // 更新n的值为平方和,继续循环
        }
    }

    public int getSum(int n) {
        String str = String.valueOf(n);  // 将n转换成字符串
        int sum = 0;
        for (int i = 0; i < str.length(); i++) {
            int num = Integer.valueOf(str.charAt(i) + "");  // 将每位字符转换成整数
            sum += num * num;  // 对每位数字进行平方操作,并将结果累加到总和中
        }

        return sum;  // 返回平方和
    }
}

1. 两数之和

题目链接:LeetCode
文章讲解:代码随想录
视频讲解:哔哩哔哩
编写语言:Java
完成状态:已完成

解题思路

  • 既有数值又有下标,优先想到哈希表中的map,而set只有key,不适用key是值,value是下标,进行遍历,查询key,返回value集合
  • 可以使用暴力法双重循环枚举查找,nums[i] + nums[j] = target时,返回对应的{i,j}即可

代码

  1. 暴力法
class Solution {
    public int[] twoSum(int[] nums, int target) {
        for (int i = 0; i < nums.length; i++) { // 遍历数组中的每一个元素
            for (int j = i + 1; j < nums.length; j++) { // 从当前元素的下一个位置开始遍历数组
                if (nums[i] + nums[j] == target) { // 如果两个数相加等于目标值
                    return new int[]{i, j}; // 返回这两个数的下标
                }
            }
        }
        return new int[]{}; // 若没有找到满足条件的两个数,则返回空数组
    }
}
  1. Map集合
class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>(); // 创建一个Map集合,用于存储数组元素和对应的索引
        for (int i = 0; i < nums.length; i++) { // 遍历数组
            int value = target - nums[i]; // 计算目标值与当前元素的差值
            boolean flag = map.containsKey(value); // 判断差值是否存在于Map中
            if (flag == true) { // 若差值存在于Map中,则找到了两个数的和等于目标值
                return new int[]{map.get(value), i}; // 返回这两个数的索引
            } else { // 若差值不存在于Map中
                map.put(nums[i], i); // 将当前元素及其索引放入Map
            }
        }
        return new int[]{}; // 若没有找到符合条件的数对,返回空数组
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值