寒假算法打卡第五天

学习目标:

第三章哈希表

  • 242.有效的字母异位词
  • 349. 两个数组的交集
  • 202. 快乐数
  • 383.赎金信

学习内容:

242.有效的字母异位词
思路:设置一个存放元素出现次数的数组,遍历s字符串时出现的元素在对应数组位置自增1,遍历t字符串时则自减1,确定在数组的下标位置时不用知道’a’对应的具体的ASCII码因为字符在计算时会自动转换为ASCII码对应的值进行计算,例如'a' - 'a' =0。
最后判断存放元素出现次数的数组中的数据是否全为0,若满足则返回true,否则证明s和t肯定有不相同的元素,因此返回false。

 public boolean isAnagram(String s, String t) {
        //设置大小为26 的数组用来存放每个字母出现的次数
        char[] hash = new char[26];

        //遍历s字符串时每个字母出现次数加1,遍历t字符串时每个字母出现次数-1
        for (int i = 0; i < s.length(); i++) {
            hash[s.charAt(i) - 'a']++;//不用直到'a‘的ASCII码,因为字符直接进行减法操作会自动转成ASCII进行计算得到对应的下标,例如:'a' - 'a' =0
        }
        for (int i = 0; i < t.length(); i++) {
            hash[t.charAt(i) - 'a']--;
        }
        //若最终存放字母出现次数的数组中数据均为0则说明满足字母异位词
        for (int i = 0; i < hash.length; i++) {
            if(hash[i] != 0){
                return false;
            }
        }

        return true;

    }

349. 两个数组的交集
(1)思路:使用Hashset,最终将结果强转位数组,将nums1数组中的数据全部存入HashSet中,HashSet会自动去重,随后用nums2数组中的数据与HashSet中的数据进行比较,若HashSet包含则将该元素存入到结果HashSet中,并且能过自动去重,最后将HashSet强制转换为数组。

  public int[] intersection_01(int[] nums1, int[] nums2) {
        //使用Hashset,最终将结果强转位数组
        if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0) {
            return new int[0];
        }
        Set<Integer> set1 = new HashSet<>();
        Set<Integer> resSet = new HashSet<>();

        //将nums1数组中的数据全部存入HashSet中,HashSet会自动去重
        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])){//contains方法表示该元素是否包含在该HashSet中
                resSet.add(nums2[i]);//若包含则添加进存放结果的HashSet中,自带去重效果
            }
        }
        return resSet.stream().mapToInt(x -> x).toArray();//返回值强制转换位数组类型


    }
      }

(2)思路:使用Hashset,最终将结果强转位数组,将nums1数组中的数据全部存入HashSet中,HashSet会自动去重,随后用nums2数组中的数据与HashSet中的数据进行比较,若HashSet包含则将该元素存入到结果HashSet中,并且能过自动去重,最后将HashSet强制转换为数组,但转换方式与上述不同。

 public int[] intersection_02(int[] nums1, int[] nums2) {
        //使用Hashset,最终将结果先转成Intefer类型数组再转成Int类型数组
        if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0) {
            return new int[0];
        }
        Set<Integer> set1 = new HashSet<>();
        Set<Integer> resSet = new HashSet<>();

        //将nums1数组中的数据全部存入HashSet中,HashSet会自动去重
        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])){//contains方法表示该元素是否包含在该HashSet中
                resSet.add(nums2[i]);//若包含则添加进存放结果的HashSet中,自带去重效果
            }
        }

        Integer[] result = resSet.toArray(new Integer[resSet.size()]);

        int[] result01 = new int[result.length];
        for (int i = 0; i < result01.length; i++) {
            result01[i] = result[i];
        }

        return result01;

    }


(3)思路:设置两个较大的数组用来存放对应数据出现的次数,随后通过判断下标相同时两个存储次数数组对应的值是否都大于0,若满足该条件则说明该下标都存在,也就是说原数组中该数据(也就是下标)都有出现过,因此可以存入集合,最终将集合的值赋予数组即可。

 public int[] intersection_03(int[] nums1, int[] nums2) {
        //设置两个较大的数组用来存放对应数据出现的次数
        int[] hash1 = new int[1002];
        int[] hash2 = new int[1002];

        for (int i = 0; i < nums1.length; i++) {
            hash1[nums1[i]]++;
        }

        for (int i = 0; i < nums2.length; i++) {
            hash2[nums2[i]]++;
        }

        //设置结果集合
        List<Integer> resList = new LinkedList<>();

        //如果同一下标对应的值都大于0则说明两个数组都存在这个下标也就是原来数组中的数据
        for (int i = 0; i < 1002; i++) {
            if(hash1[i] > 0 && hash2[i] > 0){
                resList.add(i);
            }
        }

        //设置结果数组并且接收集合数据
        int[] res = new int[resList.size()];

        for (int i = 0; i < res.length; i++) {
            res[i] = resList.get(i);
        }
        return res;

    }

202. 快乐数
思路:若该数为1则一定为快乐数;若不为1则创建一个哈希Set,用来存放计算时得出的数据,在根据规则进行计算之后,将新得出的数据与Set中存储的数据进行比较,若包含则说明是死循环则可以返回false说明原数非快乐数,若不包含则继续向下循环进行计算,每次计算要判断各个位数数字的平方和是否为1,若为1则返回true,否则继续循环判断。

public boolean isHappy(int n) {
        Set<Integer> nums = new HashSet<>();
        //n不为1并且Set不包括n才进入循环,若Set包括n说明已经进行判断过了,再进行判断结果也是一样,也就是死循环了
        while(n != 1 && !nums.contains(n)){
            nums.add(n);
            n = next(n);
            //若和为1则返回true
            if(n == 1){
                return true;
            }
        }
        //若原本是1则直接return true
        if(n == 1){
            return true;
        }
        return false;
    }

    public int next(int n){
        int sum = 0;
        int temp = 0;
        //各个位数之和
        while(n > 0){
            temp = n % 10;
            sum += temp * temp;
            n = n / 10;
        }
        return sum;
    }

383.赎金信
暴力解法:
思路:利用双for循环,每遍历magazine中的一个字符就遍历一遍ransomNote,若存在ransomNote的元素与magazine[i]相等,则将ransomNote中的该元素删除,然后i向后移动。如此循环结束后,根据判断ransomNote的长度即可判断出来ransomNote 能不能由 magazine 里面的字符构成。若长度为0则说明ransomNote 能由 magazine 里面的字符构成,否则不能,因为必然存在字符是magazine不包括的。

   public static String removeChar(int index,String Str){
        //删除ransomNote中被查找到的相同的字符
        Str=Str.substring(0,index)+Str.substring(index+1,Str.length());//substring的取值范围是:[,)
        return Str;
    }

    public boolean canConstruct_01(String ransomNote, String magazine) {
        //暴力解法
        for (int i = 0; i < magazine.length(); i++) {
            for (int j = 0; j < ransomNote.length(); j++) {
                if(magazine.charAt(i) == ransomNote.charAt(j)){//在magazine中找到ransomNote后将ransomNote的该字符删除,并且i向后移动因为magazine中的字符不能重复使用
                    ransomNote = removeChar(j,ransomNote);
                    break;
                }
            }
        }
        if(ransomNote.length() == 0){//若ransomNote的长度为0说明所有字符都被删除完成,也就说明magazine中包含全部的ransomNote字符,因此返回true
            return true;
        }
        return false;
    }

哈希表思路:

思路:与题目242.有效的字母异位词大体思路一致,设置一个数组用来存放每个元素出现的次数,magazine元素才用加法,ransomNote采用减法,若数组中存在数据小于0则说明ransomNote不能由magazine中的元素构成

 public boolean canConstruct_02(String ransomNote, String magazine){
        //与题目242.有效的字母异位词大体思路一致,设置一个数组用来存放每个元素出现的次数,magazine元素才用加法,ransomNote采用减法,若数组中存在数据小于0则说明ransomNote不能由magazine中的元素构成
        if(ransomNote.length() > magazine.length()){
            return false;
        }

        int[] nums = new int[26];

        for (int i = 0; i < ransomNote.length(); i++) {
            nums[ransomNote.charAt(i) - 'a']--;
        }
        for (int i = 0; i < magazine.length(); i++) {
            nums[magazine.charAt(i) - 'a']++;
        }
        for (int i = 0; i < nums.length; i++) {
            if(nums[i] < 0){
                return false;
            }
        }
        return true;
    }

学习时间:

下午四小时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值