算法学习 day6

文章目录

      • [242. 有效的字母异位词](https://leetcode.cn/problems/valid-anagram/)
        • 思路
        • 复杂度
      • [349. 两个数组的交集 ](https://leetcode.cn/problems/intersection-of-two-arrays/)
        • 思考
        • 复杂度
      • [202 快乐数](https://leetcode.cn/problems/happy-number/)
        • 思考(hash表-递归)
        • 复杂度
        • 思考(hash表-迭代)
        • 复杂度
        • 思考(双指针)
        • 复杂度
      • 1.两数之和
        • 思考
      • 总结

242. 有效的字母异位词

给定两个字符串 *s**t* ,编写一个函数来判断 *t* 是否是 *s* 的字母异位词,小写字母组成。

思路

  • 判断一个字符是否包含另一个字符,可想到用hash表
  • 因为单词组成字符固定为26个字母,可用数组代替hash表,下标【char - ‘1’】对应即可

复杂度

  • 时间 O(n)
  • 空间 O(1),数组长度固定为常量
class Solution {
    public boolean isAnagram(String s, String t) {
        if(t.length() != s.length()) return false; 
        int[] w = new int[26];
        for(int i = 0 ;i<s.length() ; i++){
            char c = s.charAt(i);
            w[c - 'a']++;
        }
        for(int i = 0 ;i<t.length(); i++){
            char c = t.charAt(i);
            w[c - 'a']--;
        }
        for(int i : w){
            if(i != 0 ) return false ;
        }
        return true ; 
    }
}

349. 两个数组的交集

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

思考

  • 交集即出现过得数,不考虑输出结果的顺序,符合hash结构,可想到用hash表存储已出现的数值

复杂度

  • 时间 O(n)
  • 空间 O(n)
class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> res = new HashSet<>();
        Set<Integer> sets = new HashSet<Integer>();
        for (int i = 0; i < nums1.length; i++) {
            sets.add(nums1[i]);            
        }
        for (int i = 0; i < nums2.length; i++) {
            if(sets.contains(nums2[i])){
                res.add(nums2[i]);
            }
        }

        return res.stream().mapToInt(Integer::valueOf).toArray();
    }
}

202 快乐数

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

  • 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
  • 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
  • 如果这个过程 结果为 1,那么这个数就是快乐数。

如果 n快乐数 就返回 true ;不是,则返回 false

示例 1:

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

输入:n = 2
输出:false

思考(hash表-递归)

  • 若n不是快乐数,则会无限循环,说明n在某次计算的时候会等于自己,才能出现循环,可用hash表记录每次计算结果,再次出现时return
  • 细节点:得到一个正整数n的每一位数,对n取10的模:n%10 下次n=n/10-->n==0即可

复杂度

  • 时间 O(n*m) n: 每个数字计算次数 m:每个数字的位数
  • 空间 O(n)
class Solution {
    Set<Integer> sets = new HashSet<>();

    public boolean isHappy(int n) {
        int sum = 0 ;
        while(n>0) {
            int t = n % 10;
            sum += t*t;
            n = n/10;
        }
        if(sum == 1){
            return true;
        }else if(sets.contains(sum)){
            return false;
        }else{
            sets.add(sum);
        }
        return isHappy(sum) ;
    }
}

思考(hash表-迭代)

复杂度

  • 时间 O(n*m) n: 每个数字计算次数 m:每个数字的位数
  • 空间 O(n)
class Solution {
    public boolean isHappy(int n) {
        Set<Integer> s = new HashSet<>();
        int sum = 0 ;
        while(n != 0){
            //个位的平方和
            sum += (n%10) * (n%10) ;
            n = n/10 ;
            if(n == 0){
                if(s.contains(sum)){
                    //第二次出现时一定会无限循环下去
                    return false;
                }else if (sum == 1){
                    return true;
                }else{
                    s.add(sum);
                    n = sum;
                    sum =0 ;
                }
            }
        }
        return true;
    }
}

思考(双指针)

  • 因为可能出现循环,可联想到循环链表,判断循环链表除了hash表的方式,还有快慢双针的解法
  • 此题的快慢指针为n和n~2,结束条件为n==n*n对应的快乐数,若快乐数为1,返回true,其他返回false;
  • 慢指针一次走一步,快指针要每次走两步,指针才能相遇

复杂度

  • 时间 O(n)
  • 空间 O(1)
class Solution {

    public boolean isHappy(int n) {
        int slow = n , fast = squareSum(n);
        while(slow != fast){
            slow = squareSum(slow);
            fast = squareSum(squareSum(fast));
        }
        return slow == 1 ;
    }
    public int squareSum(int n ){
        int sum = 0 ;
        while(n>0) {
            int t = n % 10;
            sum += t*t;
            n = n/10;
        }
        return sum ;
    }
}

1.两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

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

思考

  • 题目关键字:两个整数,返回下表;
  • 可想到用hash表存储已经遍历元素,如果遍历元素的差值在hash表中,即可得到结果
class Solution {
    public int[] twoSum(int[] nums, int target) {
        //map value:下标, key:存放目标值和每次遍历元素的差值
        Map<Integer,Integer> s = new HashMap<Integer,Integer>();

        for (int i = 0; i < nums.length; i++) {
            if(s.containsKey(nums[i])){
                return new int[]{s.get(nums[i]),i};
            }else{
                s.put(target - nums[i],i);
            }
        }
        return null  ;
    }
}

总结

  • 若题意中隐含有判断是否已经存在的数值时,首先可想到hash表(HashSet\HashMap)
  • 若字符数量为常量,可试用数组代替hash表,节省空间

你可能感兴趣的:(算法,算法,学习)