代码随想录刷题|LeetCode 242.有效的字母异位词 349. 两个数组的交集 202. 快乐数 1. 两数之和

简介: 代码随想录刷题|LeetCode 242.有效的字母异位词 349. 两个数组的交集 202. 快乐数 1. 两数之和

242.有效的字母异位词

题目链接: 力扣                                  

思路

  这道题目是要判断来判断 t 是否是 s 的字母异位词。其本质就是判断这两个字符串中的字符出现的种类和次数是否都是一样的。因为26个字母的字符编码是连续的数字,字母的数字是固定的,而且也是连续的,所以可以创建一个长度为26的数组来记录每个字母出现的次数


       如果要判断的不是单纯的小写英文字母,没有规律,此时就要换一种记录方式了,使用Map集合记录更为合适,没有特别的长度限制


有效的字母异位词

对于只有纯小写英文字母的判断:


  第一步:创建数组容器

       第二步:遍历s字符串,通过增加数字记录每个字母出现的次数

       第三步:遍历t字符串,通过减小数字记录每个字母出现的次数

       第四步:判断数组中的全部是否为0

class Solution {
    public boolean isAnagram(String s, String t) {
        if (s.length() != t.length()) {
            return false;
        }
        // 使用数组作为哈希表记录每个字母出现的次数
        // 首先创建数组容器
        int[] record = new int[26];
        // 遍历s字符串,通过增加数字记录每个字母出现的次数
        for (int i = 0 ; i < s.length() ; i++) {
            record[s.charAt(i) - 'a']++;
        } 
        // 遍历t字符串,通过减小数字记录每个字母出现的次数
        for (int i = 0 ; i < t.length() ; i++) {
            record[t.charAt(i) - 'a']--;
        }
        // 判断是否数组中全部的数字为0
        for (int i = 0 ; i < record.length ; i++) {
            if ( record[i] != 0 ) {
                return false;
            }
        }
        return true;
    }
}

对于UniCode编码的字符的判断:

       使用Map作为容器

class Solution {
    public boolean isAnagram(String s, String t) {
        if (s.length() != t.length()) {
            return false;
        } 
        // 创建容器
        Map<Character,Integer> maps = new HashMap<>();
        // 遍历第一个字符串
        for (int i = 0 ; i < s.length() ; i++) {
            char ch = s.charAt(i);
            maps.put(ch,maps.getOrDefault(ch,0) + 1);
        }
        // 遍历第二个字符串
        for (int i = 0 ; i < t.length() ; i++) {
            char ch = t.charAt(i);
            maps.put(ch,maps.getOrDefault(ch,0) - 1);
            if (maps.get(ch) < 0) {
                return false;
            } 
        }
        return true;
    }
}


349. 两个数组的交集

题目链接:力扣

思路


    首先这个题目的两个注意点:1、结果中的元素一定是唯一的 2、不考虑输出结果的顺序 。这种情况下最容易想到的就是Set集合。set集合的特点就是无序不可重复。


       所以首先将nums1的所有数字记录到一个set1集合中,此时这个set1集合中是nums1的所有出现过的数字


       再次遍历nums2数组,如果再set1集合中包含这个数字,就将数字记录到set2集合中


两个数组的交集

       第一步:对数组nums1进行遍历,将数字添加到set集合中

       第二步:遍历nums2数组,将再set1集合中出现过的数组记录到set2中

       第三步:将set2集合转换成int[]数组



不常用的知识点:

       将set集合转换成int[]数组

       setNums2.stream().mapToInt(x -> x).toArray();

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        // 创建容器,这里采用Set集合,无序不可重复
        Set<Integer> setNums1 = new HashSet<>();
        Set<Integer> setNums2 = new HashSet<>();
        // 对数组nums1进行遍历,将数字添加到set集合中
        for (Integer i : nums1) {
            setNums1.add(i);
        }
        for (Integer i : nums2) {
            // 这里写复杂了,忘记contains()方法了
            /**
            for (Integer j : setNums1) {
                if (i.equals(j)) {
                    setNums2.add(i);
                }
            }
             */
            if (setNums1.contains(i)) {
                setNums2.add(i);
            }
        }
        return setNums2.stream().mapToInt(x -> x).toArray();
    }
}


202. 快乐数

题目链接:力扣

思路

    还是要注意读题,一开始自己思考的时候就是想着怎么判断这个数字知道1,忽略了题目中所说的会出现无限循环的情况


       这个题目的两个难点:

               1、一个难点就是求和的过程,如果对取数值各个位上的单数操作不熟悉的话,做这道题

也会比较艰难

               2、判断不断地将一个数的每一位数字平方和后的走向,能判断出出现的情况,才能通过其中的原理来选择合适的集合        


b351238b83834d9fa93e724a30875ab6.png


 来自力扣官方:我们使用哈希集合而不是向量、列表或数组的原因是因为我们反复检查其中是否存在某数字。检查数字是否在哈希集合中需要 O(1)的时间,而对于其他数据结构,则需要 O(n)的时间。选择正确的数据结构是解决这些问题的关键部分。

快乐数

 第一步:照题目的要求做数位分离,求平方和

       第二步:判断出了数字的走向就两种情况,要么最后是1,要么最后就是在无限循环,那就不断去判断就好了,这也是为什么选择set集合的原因(因为set集合无序不可重复)

class Solution {
    public boolean isHappy(int n) {
        Set<Integer> serNums = new HashSet<>();
        while (n != 1 && !serNums.contains(n)) {
            serNums.add(n);
            n = getNextNumber(n);
        }
        return n == 1;
    }
    // 取各个位上的数值
    public int getNextNumber(int num) {
        int sum = 0;
        while (num > 0) {
            int temp = num % 10;
            sum += temp * temp;
            num = num / 10;
        }
        return sum;
    }
}


1. 两数之和

题目链接:力扣

思路


当需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法

       我们不仅要知道元素有没有遍历过,还有知道这个元素对应的下标,需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适。


       哈希法还有两种就是数组和Set,用数组查找我们还有知道元素对应的下标,那就相当于暴力解法了。set只能存数字不重复,我还需要一个下标进行存储,所以使用map比较合适

       而且使用map的时候,需要考虑两个一样的数等于目标和的情况:如果先把所有的数都存进map里面,会把重复的数字和下标略去,所以一定要边添加边判断


两数之和

暴力解法


class Solution {
    public int[] twoSum(int[] nums, int target) {
        // 创建数组接收结果 
        int[] result = new int[2];
        // 遍历nums集合,得到每一个数字与目标值对应的差
        for (int i = 0; i < nums.length ; i++) {
            for (int j = i + 1; j < nums.length ; j++) {
                if (nums[i] + nums[j] == target) {
                    result[0] = i;
                    result[1] = j;
                }
            }
        }
        return result;
    }
}

哈希法

       第一步:创建接收下标的集合,创建Map集合

       第二步:遍历数组,判断集合中是否有满足teaget-nums[i] 存在的数字

       第三步:如果不存在,就将此时的数字和对应的下标添加到集合中,如果存在就将此时对应的两个数字的下标存储到数组中

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result = new int[2];
        Map<Integer,Integer> mapNums = new HashMap<>();
        for (int i = 0 ; i < nums.length ; i++) {
            int temp = target - nums[i];
            if (mapNums.containsKey(temp)) {
                result[0] = i;
                result[1] = mapNums.get(temp);
            }
            mapNums.put(nums[i],i);
        }
        return result;
    }
}

要注意一个点就是面对重复的的数字,如果先将数字全部移到Map集合中,重复的就不能收集进去了。比如[3,3],使用下面这种方法就会返回[1,1],结果应该是[0,1]的,以下是错误的代码:(记录一下,这种写法忽略了[3,3]这种情况)

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result = new int[2];
        Map<Integer,Integer> mapNums = new HashMap<>();
        for (int i = 0 ; i < nums.length ; i++) {
            mapNums.put(nums[i],i);
        }
        for (int i = 0 ; i < nums.length ; i++) {
            if (mapNums.containsKey(target - nums[i])) {
                result[0] = i;
                result[1] = mapNums.get(target - nums[i]);
            }
        }
        return result;
    }
}
相关文章
|
2月前
|
算法
Leetcode 初级算法 --- 数组篇
Leetcode 初级算法 --- 数组篇
40 0
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
280页PDF,全方位评估OpenAI o1,Leetcode刷题准确率竟这么高
【10月更文挑战第24天】近年来,OpenAI的o1模型在大型语言模型(LLMs)中脱颖而出,展现出卓越的推理能力和知识整合能力。基于Transformer架构,o1模型采用了链式思维和强化学习等先进技术,显著提升了其在编程竞赛、医学影像报告生成、数学问题解决、自然语言推理和芯片设计等领域的表现。本文将全面评估o1模型的性能及其对AI研究和应用的潜在影响。
25 1
|
2月前
【LeetCode-每日一题】 删除排序数组中的重复项
【LeetCode-每日一题】 删除排序数组中的重复项
21 4
|
2月前
|
索引
Leetcode第三十三题(搜索旋转排序数组)
这篇文章介绍了解决LeetCode第33题“搜索旋转排序数组”的方法,该问题要求在旋转过的升序数组中找到给定目标值的索引,如果存在则返回索引,否则返回-1,文章提供了一个时间复杂度为O(logn)的二分搜索算法实现。
19 0
Leetcode第三十三题(搜索旋转排序数组)
|
2月前
|
算法 C++
Leetcode第53题(最大子数组和)
这篇文章介绍了LeetCode第53题“最大子数组和”的动态规划解法,提供了详细的状态转移方程和C++代码实现,并讨论了其他算法如贪心、分治、改进动态规划和分块累计法。
68 0
|
2月前
|
C++
【LeetCode 12】349.两个数组的交集
【LeetCode 12】349.两个数组的交集
17 0
|
3月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
4月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
58 6
|
4月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
120 2
|
3月前
|
数据采集 负载均衡 安全
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口