代码随想录第五天

题目:242. 有效的字母异位词

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

样例:
输入: s = "anagram", t = "nagaram"
输出: true

输入: s = "rat", t = "car"
输出: false
Map 实现

思路,使用HashMap 存入每一个 s 字符串的字符,如果存在则值加一,不存在则创建;遍历 t 字符串,如果存在则减一; 最后查看是否存在值不为0的key。

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);
            char d = t.charAt(i);
            if (c == d) {
                continue;
            } else {
                map.put(c, map.getOrDefault(c, 0) + 1);
                if(map.containsKey(d)){
                    map.put(d, map.get(d)-1);
                }else{
                    map.put(d, -1);
                }
            }
        }
        for (char key : map.keySet()) {
            if(map.get(key) != 0){
                return false;
            }
        }
        return true;


    }

数组实现

思路:该解法与上面 Map实现 一样,同样是遍历,但是解法考虑到字符的ASCII 值,因此可以创建固定长度的数组来解决问题

 public boolean isAnagram(String s, String t) {
        if (s.length() != t.length()) {
            return false;
        }
        int[] alpha = new int[26];
        for (int i = 0; i < s.length(); i++) {
            alpha[s.charAt(i) - 'a']++;
            alpha[t.charAt(i) - 'a']--;
        }
        for (int i = 0; i < 26; i++) {
            if (alpha[i] != 0)
                return false;
        }
        return true;
    }
剪枝实现 
 

剪枝:剪枝的目的是通过提前终止某些计算分支或减少搜索空间,以避免无效的计算或搜索不必要的路径,从而优化算法的执行时间或减少内存消耗。
思路:在数组解法的基础上,可以通过判断,提前走出循环搜索
 

public boolean isAnagram(String s, String t) {
        if (s.length() != t.length()) {
            return false;
        }
        int[] alpha = new int[26];
        for (int i = 0; i < s.length(); i++) {
            alpha[s.charAt(i) - 'a']++;
        }
        for (int i = 0; i < t.length(); i++) {
            alpha[t.charAt(i) - 'a']--;
            if (alpha[t.charAt(i) - 'a'] < 0) {
                return false;
            }
        }
        return true;
    }

题目:349. 两个数组的交集
 

给定两个数组 nums1 和 nums2 ,返回 它们的 交集。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
 

样例:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4] 或 [4,9]
集合实现 

思路:分别对两个数组进行遍历,将其中的数据存入Set 集合中。其中第二个集合判断数据是否存在于第一个集合中,存在则加入,最后将第二个集合转为数组返回。

public int[] intersection(int[] nums1, int[] nums2) {
        if (nums1 == null || nums2 == null || nums1.length == 0 || nums2.length == 0) {
            return new int[0];
        }
        Set<Integer> set1 = new HashSet<Integer>();
        Set<Integer> set2 = new HashSet<Integer>();
        for (int i = 0; i < nums1.length; i++) {
            set1.add(nums1[i]);
        }
        for (int i = 0; i < nums2.length; i++) {
            if (set1.contains(nums2[i])) {
                set2.add(nums2[i]);
            }
        }
        return set2.stream().mapToInt(x -> x).toArray();
    }
双指针 

思路:将数组有序化后,使用双指针进行移动

public int[] intersection(int[] nums1, int[] nums2) {
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        int len1 = nums1.length;
        int len2 = nums2.length;
        int[] res = new int[len1 + len2];
        int index = 0, index1 = 0, index2 = 0;
        while (index1 < len1 && index2 < len2) {
            int num1 = nums1[index1], num2 = nums2[index2];
            if (num1 == num2) {
                if (index == 0 || num1 != res[index - 1]) {
                    res[index++] = num1;
                }
                index1++;
                index2++;
            } else if (num1 < num2) {
                index1++;
            } else {
                index2++;
            }
        }
        return Arrays.copyOfRange(res, 0, index);
    }
剪枝
 

思路:根据提示,数组大小控制在一定范围内,因此可以使用数组来模拟hash, 与 242.有效的字母异位词 一样

public int[] intersection(int[] nums1, int[] nums2) {
       int hash[]=new int[1001];
        int []res=new int[nums1.length+nums2.length];
        for (int i = 0; i <nums1.length ; i++) {
         hash[nums1[i]]=1;   
        }
        int t=0;
        for (int i = 0; i <nums2.length ; i++) {
            if(hash[nums2[i]]==1){
                hash[nums2[i]]=0;
                res[t++]=nums2[i];
            }
        }
        res=Arrays.copyOf(res,t);
        return res;
    }

题目:202. 快乐数
 

样例:

输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

输入:n = 2
输出:false
暴力+Set 判断

思路:先遍历获取每一步每一位的值,然后把值加入 set 集合中,如果 set 中存在这个数,则说明原始值在算法中不断循环,即得不到1, 返回false

public boolean isHappy(int n) {
        Set<Integer> set = new HashSet<>();
        int tmp = getSum(n);
        while (!set.contains(tmp)) {
            if(set.size() == 0){
                set.add(tmp);
            }
            if (tmp == 1) {
                return true;
            }
            set.add(tmp);
            tmp = getSum(tmp);
        }
        return false;
    }

    public int getSum(int num) {
        int sum = 0;
        while (num != 0) {
            int remain = num % 10;//余数
            num = num / 10;
            sum += remain * remain;
        }
        return sum;
    }
 官方题解-快慢指针:
 

思路: 在上面解法的基础上进行优化,类似 第四天中的环形链表 ,使用快慢指针,考虑到如果存在循环,那么两个指针必定相遇,然后判断相遇的值即可。

 

public boolean isHappy(int n) {
        int slowRunner = n;
        int fastRunner = getSum(n);
        while (fastRunner != 1 && slowRunner != fastRunner) {
            slowRunner = getSum(slowRunner);
            fastRunner = getSum(getSum(fastRunner));
        }
        return fastRunner == 1;
    }


    public int getSum(int num) {
        int sum = 0;
        while (num != 0) {
            int remain = num % 10;//余数
            num = num / 10;
            sum += remain * remain;
        }
        return sum;
    }

题目:1. 两数之和

样例:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
输入:nums = [3,3], target = 6
输出:[0,1]
暴力

时间复杂度O(n*2)

思路:双重 for 循环遍历, 判断指定数是否存在数组中

public int[] twoSum(int[] nums, int target) {
        int tmp;
        for (int i = 0; i < nums.length - 1; i++) {
            tmp = target - nums[i];
            for (int j = i + 1; j < nums.length; j++) {
                if (nums[j] == tmp) {
                    return new int[] { i, j };
                }
            }
        }
        return new int[] { -1, -1 };
    }
Hash
 

思路:使用 hash 表来减少一次 for 循环遍历 target - nums[i] 是否存在
 

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

  • 16
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值