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

一、哈希函数的抉择

数组:哈希值小而且范围小

set:哈希值大且范围大

map:需要有key value 的对应


二、有效的字母异位词

----要点:s.charAt(i)这里涉及一个string取字符的操作 ,取得第i个位置的字符

因为之前没有做过哈希的题目所以整个人是很懵的,但是听完讲解后,写出算法逻辑是没问题的

但是对于一些代码的书写还是有误的,例如

    hasharray[s.charAt[i]-"a"]++; //错误代码
    hasharray[s.charAt(i)-'a']++;  //正确代码

例如[]里写双引号还有charAt(i)写出charAt[i]

数组的长度是 .length        然而 字符串String的长度是.length()


以下为实现代码 

    public boolean isAnagram(String s, String t) {
            int[] hasharray = new int[26];  //因为是26个字母
            //然后给哈希数组赋初值0
            for(int i=0;i<hasharray.length;i++){
                hasharray[i]=0;
            }
            //接下来遍历第一个字符串s,进行操作
            //s.charAt(i)这里涉及一个string取字母的操作
            for(int i=0;i<s.length();i++){
                hasharray[s.charAt(i)-'a']++;
            }
            for(int i =0;i<t.length(); i++){
                hasharray[t.charAt(i)-'a']--;
            }
            //操作完毕后对哈希数组进行遍历检查
            for(int i =0;i<hasharray.length;i++ ){
                if(hasharray[i]!=0){
                    return false;
                }
            }
        return true;
    }

三、两个数组的交集

 重点---数组来做哈希的题目,是因为题目都限制了数值的大小

  而这道题目没有限制数值的大小,就无法使用数组来做哈希表了。

  而且如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费

-->做这种不熟悉的题目其实就是一个完全新的学习过程,其实运行的逻辑并不复杂,但是需要多熟悉一下集合的操作,然后还有一个遍历集合转数组的操作

public int[] intersection(int[] nums1, int[] nums2) {
        //-------这题选择用set解决,因为不知道数组里的值的大小,
        //      如果是很大并且数据分散的话,用数组就会很浪费
        Set<Integer> set1 = new HashSet<>();    //建立一个hashset
         Set<Integer> resSet = new HashSet<>();

        for(int i =0 ;i<nums1.length;i++){
            set1.add(nums1[i]);     //这里直接用hashset add 值就可以了,他会自己转化的
        } 

        for(int i =0; i<nums2.length;i++){
            if (set1.contains(nums2[i])) {   //判断是否contains
                resSet.add(nums2[i]);        //用新的哈希表进行增加,哈希表的好处是可以去重
            }
        }
        //--------这里还有一个挺上流的操作,将set转化为数组
        int[] intersection = new int[resSet.size()];
        int index = 0;
        for (int num : resSet) {
            intersection[index++] = num;
        }
        //将结果几何转为数组
        return intersection;
    }

四、快乐数

题目灵魂:使用哈希法,来判断这个sum是否重复出现

------他不是一个纯纯的重复循环的题目,我们需要有一种合理的措施来判断计算出来的值是否出现过的,所以这个时候用hashset就很舒服啦 

 -->这题都没有看视频就懂了诶~~(写完才发现原来也没有视频....)  ,虽然那个对一个数按位置不断的遍历的操作是真滴上流,还是看了给的代码。

使用hashset做(随想录做法)

public boolean isHappy(int n) {
       Set<Integer> set1 = new HashSet<>();    //建立一个hashset
        //问题点一:题设给的int 我怎么去获得十位和个位的值
       int i = n;
       int all = 0;
       while(!set1.contains(i)){
            set1.add(i);
        //问题解决点:int temp = n % 10;这可是数学问题嗷
   /*         int ge = i%10;
            int shi = i/10;
            i = ge*ge+shi*shi;  //但很显然我这样做其实是有一点问题的,无法对每一个位置的值进行操作
   */       n = i;
             while (n > 0) {
            int temp = n % 10;
            all += temp * temp;
            n = n / 10;
        }     //这个算法就很吊,他通过循环直接就不断的对每一位进行操作

            if(all==1 ){
                return true;
            }
            System.out.println(all);
            i=all; all=0;
       }   
        return false;
    }
}

------ //问题点一:题设给的int 我怎么去获得十位和个位的值

-------//问题解决点:int temp = n % 10;这可是数学问题嗷

---->用个循环遍历的算法,每次一位一位的挪动,当/10后判断<0后脱离循环即可!!!!

(这种思想嘎嘎重要)

使用双指针做(力扣做法)--》经典的循环追击问题

public boolean isHappy(int n) {
        //力扣推荐双指针算法
        int fast =culmulate(n);
        int slow = n;
         while(fast!=slow && fast!=1){ //这里必须是&&--->不然如果fast!=1,即便相等还是会不断地循环
         //原因:快乐数的条件是能fast=1;并且不成环 
          //如果触碰到了1,那么循环的值就会是一直是1,所以循环判出条件还有1
             fast=culmulate(fast);
             fast=culmulate(fast);
             slow=culmulate(slow);
             System.out.println("fast"+fast);
             System.out.println("slow"+slow)

         }
         
        return fast==1;
    }
    //---这里先写下n的各个位置平方和的算法
    public  int culmulate(int n ){
             int all = 0;
             while(n>0){
                 int a = n%10;
                 all=all+a*a;
                 n=n/10;
             }
             return all;
         }

------->这里的判断环的思路和链表那道题的思路是一毛一样的

五、两数之和

因为本地,我们不仅要知道元素有没有遍历过,还有知道这个元素对应的下标,需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适

再来看一下使用数组和set来做哈希法的局限。

  • 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
  • set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用

-------->去看了卡哥的视频后理解了整个map的操作了,自己也能盲写出来了 

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

----哈希表总结:之前因为对于哈希表的恐惧导致我一直不敢写,然后拖到不能再拖的时候,才发现其实不会写是正常的,对于一个陌生的东西就是一个学习的过程,边看视频,边写,其实真的没问题啦 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值