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

目录

242.有效的字母异位词

思路

有效的字母异位词

349. 两个数组的交集

思路

两个数组的交集

202. 快乐数

思路

快乐数

1. 两数之和

思路

两数之和

暴力解法

哈希法


242.有效的字母异位词

题目链接: 力扣                                   

思路

        这道题目是要判断来判断 是否是 的字母异位词。其本质就是判断这两个字符串中的字符出现的种类和次数是否都是一样的。因为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、判断不断地将一个数的每一位数字平方和后的走向,能判断出出现的情况,才能通过其中的原理来选择合适的集合       

       来自力扣官方:我们使用哈希集合而不是向量、列表或数组的原因是因为我们反复检查其中是否存在某数字。检查数字是否在哈希集合中需要 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;
    }
}

给定一个整数组 nums 和一个目标值 target,要求在数组中找出两个的和等于目标值,并返回这两个的索引。 思路1:暴力法 最简单的思路是使用两层循环遍历数组的所有组合,判断两个的和是否等于目标值。如果等于目标值,则返回这两个的索引。 此方法的时间复杂度为O(n^2),空间复杂度为O(1)。 思路2:哈希表 为了优化时间复杂度,可以使用哈希表来存储数组中的元素和对应的索引。遍历数组,对于每个元素nums[i],我们可以通过计算target - nums[i]的值,查找哈希表中是否存在这个差值。 如果存在,则说明找到了两个的和等于目标值,返回它们的索引。如果不存在,将当前元素nums[i]和它的索引存入哈希表中。 此方法的时间复杂度为O(n),空间复杂度为O(n)。 思路3:双指针 如果数组已经排序,可以使用双指针的方法来求解。假设数组从小到大排序,定义左指针left指向数组的第一个元素,右指针right指向数组的最后一个元素。 如果当前两个指针指向的的和等于目标值,则返回它们的索引。如果和小于目标值,则将左指针右移一位,使得和增大;如果和大于目标值,则将右指针左移一位,使得和减小。 继续移动指针,直到找到两个的和等于目标值或者左指针超过了右指针。 此方法的时间复杂度为O(nlogn),空间复杂度为O(1)。 以上三种方法都可以解决问题,选择合适的方法取决于具体的应用场景和要求。如果数组规模较小并且不需要考虑额外的空间使用,则暴力法是最简单的方法。如果数组较大或者需要优化时间复杂度,则哈希表或双指针方法更合适。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值