Day6——有效的字母异位词、两个数组的交集、快乐数、两数之和(哈希)

简介: Day6——有效的字母异位词、两个数组的交集、快乐数、两数之和(哈希)

前言


今日文案:

盐于律己,甜以待人

一、有效的字母异位词


题目描述:

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

注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

题目来源:

力扣

解题思路:


本题主要是用的哈希结构是——数组。因为我们可以看到,我们的对象只是26个字母,长度比较小,所以我们可以创作数组结构来实现,如果很大的话我们会浪费很多空间。

数组的哈希结构,主要是我们创建一个哈希数组(就是普通数组,我们叫哈希数组是为了区分而已),然后去把目标数组遍历,把目标数组的值 通过处理,然后变成数组的下标,对应下标的哈希数组++,这样我们就可以通过比对找出我们想要的结果。

代码如下:

bool isAnagram(char * s, char * t){
    int arr[26]={0},a=1;
    for(int i=0;i<strlen(s);i++)            //遍历数组
    {    
        arr[s[i]-'a']++;                    //利用阿斯卡码值,得出对应下标++
    }
    for(int i=0;i<strlen(t);i++)
    {
        arr[t[i]-'a']--;          //这里注意是减减(外边有说明)
    }                          
    for(int i=0;i<26;i++)                    //如果你最后的数组都是0,说明字母出现次数是一样的                
    {
        if(arr[i]!=0)
        a=0;
    }
    if(a==0)
    return false;
    else
    return true;
}

关于那个- -的地方,也是我踩的一个坑,我最初的想法是,我都是++,然后数组里面出现的不是2就是0,不久可以认为两个字符串是一对一对出现的吗,这样不久等于消消乐一样,简简单单吗。

但是消消乐会消,我这里没有写啊,鬼知道一个字符串里面相同的字母会出现多少次次呢,因此我们通过- -来判断,==0就说明他们两个相互抵消辣~

二、两个数组的交集


问题来源:

力扣

1.数组解法(c)


上面我们学习了数组解法,我这题也尝试着使用了一下。因为要求两个数组的交集,那我们只要使用哈希数组,把数组出现的元素都保存好,然后用两个哈希数组一比对就知道是不是同时出现了。

代码如下:

int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
    int *p=(int *) malloc(sizeof(int)*1000);    //申请空间作为存放答案的地方
    int arr[1001]={0},brr[1001]={0},j=0;        //定义两个数组,作为哈希数组
    for(int i=0;i<nums1Size;i++)
    {
        arr[nums1[i]]++;                        //做第一个数组的哈希表
    }
    for(int i=0;i<nums2Size;i++)
    {    
        brr[nums2[i]]++;                        //第二个数组的哈希表
    }
    for(int i=0;i<1000;i++)
    {
        if(arr[i]>0&&brr[i]>0)            //比对两个哈希数组,同时大于0,是明是交集
        {
            p[j]=i;                    //保存好
            j++;
        }
    }
    *returnSize=j;                    //返回
    return p;
}

上面那种方法比较简单易懂,但是low,肯定有小伙伴不满足于此,下面我来解释另外一种哈希结构——set.

2、set解法(c++)


按我的理解(初学):unordered_set<int> 这种结构,它是可以自动帮你筛除去重复的元素,也就是说,储存的元素都是不重复的,而且空间是比较有弹性的,不需要像数组一样一次定义,可能会造成浪费。

代码如下:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> ans;
        int has[1000]={0},a=0;
        for(int i=0;i<nums1.size();i++)            //把目标数组1的值作为下标对应哈希数组置1
        {
            has[nums1[i]]=1;
        }
        for(int i=0;i<nums2.size();i++)    //用目标数组2的值作为下标索引
        {
            if(has[nums2[i]]==1)            //如果也等于1,那么说明是相交的
            {
                ans.insert(nums2[i]); //这里是插入相交的值,因为set,是不会插入重复的值的
                a++;
            }
        }
        return vector<int>(ans.begin(), ans.end());  //返回
    }
};

三、快乐数


题目来源:

力扣

思路:

1、首先我们可以看见,这个快乐数好像和我们的水仙花数有点类似,都是用每一位的和的平分加起来。但不一样的是,水仙花数只需要一次就可以判断了,但这个好像需要很多次,而且有可能进入死循环。

2、我们怎么判断死循环呢,当一个结果在里面重复出现了,我们就可以判断是死循环了,是一辈子得不到那个1的。

代码如下(示例):

int f(int n)                //计算函数
{
    int sum=0;
    while(n)
    {
        sum=(n%10)*(n%10)+sum;        //拆数
        n=n/10;
    }
    return sum;
}
class Solution {
public:
    bool isHappy(int n) {
        unordered_set<int> p;        //一个set结构
        while(1)
        {
            int sum=f(n);            //每次计算一次
            if(sum==1)
            return true;
            if(p.find(sum)!=p.end())        //因为find如果找不到那个值,它会=p.end()
            return false;
            else{
            p.insert(sum);            //如果没有找到1,也还没有判断进入死循环,把当前的sum插
            }                            入set里面,以后可以判断是否出现死循环
            n=sum;        //新的一轮起始数
        }
    }
};

四、两数之和


力扣第一题,真就,有人夜里开车看海,有人谈情说爱,有人力扣第一道题都写不出来呗。

题目来源:

力扣

思路:

1、暴力破解,没什么技术难度,两个for搞定。

2、用map。

代码如下:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> map;
        for(int i=0;i<nums.size();i++)
        {
            int w=target-nums[i];
            auto adr=map.find(w);
            if(adr!=map.end())
            return {adr->second,i};
            else
            map.insert(pair<int,int>(nums[i],i));
        }
        return {};
    }
};

关于map,我也没有了解得很明白,下面是我一点粗浅的理解:

map里面有两个数据类型,一个存地址一个存值,我们在这里只需要两步

1、搜索以前有没有出现这个值

2、存储出现的值

下面是四个需要思考的问题:


1、为什么想到用哈希法。

2、我们为什么要用map。

3、map究竟是用来干什么的。

4、map里面的key是用来存什么的。

ps :图书馆要关门了,交给你们了hhh

总结


今天是算法训练的第六天,新学了很多c++的东西,我也准备使用c++刷题了,加油加油!!!

相关文章
|
6月前
|
算法
LeetCode算法题---无重复字符的最长子串、寻找两个正序数组的中位数(三)
LeetCode算法题---无重复字符的最长子串、寻找两个正序数组的中位数(三)
63 0
|
API
代码随想录 Day5 哈希表1 T242 相同字母的异序词 T349两个数组的交集 T202 快乐数 T1 两数之和(下)
代码随想录 Day5 哈希表1 T242 相同字母的异序词 T349两个数组的交集 T202 快乐数 T1 两数之和(下)
37 0
|
6月前
力扣421. 数组中两个数的最大异或值(字典树)
力扣421. 数组中两个数的最大异或值(字典树)
|
6月前
|
Python C++ Java
C/C++每日一练(20230407) 选择排序法、多数元素、字母异位词分组
C/C++每日一练(20230407) 选择排序法、多数元素、字母异位词分组
60 0
C/C++每日一练(20230407) 选择排序法、多数元素、字母异位词分组
|
6月前
|
算法
LeetCode题:581. 最短无序连续子数组,242. 有效的字母异位词,202. 快乐数
LeetCode题:581. 最短无序连续子数组,242. 有效的字母异位词,202. 快乐数
51 0
|
11月前
|
存储 算法
【LeetCode】每日一题&最后一个单词的长度&投票法求解多数元素&异或操作符巧解只出现一次的数字&整数反转
【LeetCode】每日一题&最后一个单词的长度&投票法求解多数元素&异或操作符巧解只出现一次的数字&整数反转
【剑指offer】-数字在排序数组中出现的次数-32/67
【剑指offer】-数字在排序数组中出现的次数-32/67
|
11月前
|
算法 测试技术 C#
C++二分查找算法的应用:第 N 个神奇数字
C++二分查找算法的应用:第 N 个神奇数字
|
Serverless 索引
代码随想录 Day5 哈希表1 T242 相同字母的异序词 T349两个数组的交集 T202 快乐数 T1 两数之和(上)
代码随想录 Day5 哈希表1 T242 相同字母的异序词 T349两个数组的交集 T202 快乐数 T1 两数之和
68 0
|
存储 算法 C++
【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和
【数据结构与算法】哈希表1:字母异位词 & 两数交集 & 快乐数 & 两数之和
82 0