代码随想录刷题|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;
    }
}
相关文章
|
1月前
|
算法
Leetcode 初级算法 --- 数组篇
Leetcode 初级算法 --- 数组篇
38 0
|
3月前
|
算法
LeetCode第53题最大子数组和
LeetCode第53题"最大子数组和"的解题方法,利用动态规划思想,通过一次遍历数组,维护到当前元素为止的最大子数组和,有效避免了复杂度更高的暴力解法。
LeetCode第53题最大子数组和
|
3月前
|
存储 算法
LeetCode第49题字母异位词分组
LeetCode第49题"字母异位词分组"的解题方法,通过将每个字符串的字符排序后作为键存储在HashMap中,有效地将所有字母异位词分组。
LeetCode第49题字母异位词分组
LeetCode------找到所有数组中消失的数字(6)【数组】
这篇文章介绍了LeetCode上的"找到所有数组中消失的数字"问题,提供了一种解法,通过两次遍历来找出所有未在数组中出现的数字:第一次遍历将数组中的每个数字对应位置的值增加数组长度,第二次遍历找出所有未被增加的数字,即缺失的数字。
|
1月前
【LeetCode-每日一题】 删除排序数组中的重复项
【LeetCode-每日一题】 删除排序数组中的重复项
19 4
|
1月前
|
存储
Leetcode第49题(字母异位词分组)
LeetCode第49题要求将字符串数组中的字母异位词分组,可以通过将每个字符串排序后作为键存入哈希表,最后将哈希表中的值添加到结果列表中来实现。
14 1
|
1月前
|
索引
Leetcode第三十三题(搜索旋转排序数组)
这篇文章介绍了解决LeetCode第33题“搜索旋转排序数组”的方法,该问题要求在旋转过的升序数组中找到给定目标值的索引,如果存在则返回索引,否则返回-1,文章提供了一个时间复杂度为O(logn)的二分搜索算法实现。
18 0
Leetcode第三十三题(搜索旋转排序数组)
|
1月前
|
算法
Leetcode第十七题(电话号码的字母组合)
这篇文章介绍了如何使用深度优先搜索(DFS)算法来解决LeetCode第17题——电话号码的字母组合问题,通过递归方法生成所有可能的字母组合。
15 0
Leetcode第十七题(电话号码的字母组合)
|
1月前
|
C++
Leetcode第一题(两数之和)
这篇文章介绍了解决LeetCode第一题“两数之和”的两种方法:暴力法和哈希表法,并提供了相应的C++代码实现。
27 0
Leetcode第一题(两数之和)
|
1月前
|
索引
【LeetCode 11】242.有效的字母异位词
【LeetCode 11】242.有效的字母异位词
13 0
【LeetCode 11】242.有效的字母异位词