代码随想录(day6)——哈希表

Leetcode.242 有效的字母异位词:

242. 有效的字母异位词 - 力扣(LeetCode)

       原理简单,首先判断给定的两个字符串的长度是否相等,如果不相等则直接返回false,只有在给定字符串长度想的的情况下才进行下一步的判断。

      当给定的元素相等时,首先创建名为hashhash1的两个数组,数组大小为26,并且对st字符串进行遍历,在遍历的过程中,使hash[s[i]-'a']位置的数值++,hash[t[i]-'a']位置的数值++。

      遍历hash,hash1两个数组,如果出现了hash[i] \, \, != \, \, hash1[i]的情况,则直接返回false。遍历结束后返回true。对于代码如下:

class Solution {
public:
    bool isAnagram(string s, string t) {

        int hash[26] = {0};
        int hash1[26] = {0};

        if( s.size() != t.size())
        {
            return false;
        }

        for(size_t i = 0; i < s.size(); i++)
        {
            hash[s[i]-'a']++;
            hash1[t[i]-'a']++;
        }

        for(int j  = 0; j < 26; j++)
        {
            if(hash[j] != hash1[j])
            {
                return false;
            }
        }

        return true;

    }
};

运行结果如下:

(注:在下面给出的题目解析中,会涉及到map,set的使用,由于作者本人水平有限,并不能给出关于这两种数据结构的相关解释,因此只给出使用方法,对于这两种数据结构进行解析的文章,将在20244月之前给出。)

Leetcode.349 两个数组的交集:

349. 两个数组的交集 - 力扣(LeetCode)

       本题虽然使用set会更加方便,但是并不是刚性要求,因此介于作者水平有限,将使用vector进行解答:

      首先创建一个大小大于1000的数组hash,遍历数组nums1,使得hash[nums1[i]]=1。在遍历完成后,遍历另一个数组nums2,如果hash[nums2[i]] ==1,则说明该该数值在nums1种出现过,需要进行记录。

      对于如何记录,可以创建一个vector<int>类型的对象result,如果出现了满足上面给出的条件的数据,则通过push_back函数进行插入。并且,为了满足交集的性质,即:集合中不能出现重复的元素。需要进行去重。

      去重的方法如下:在进行了push_back操作后,则令hash[nums2[i]]=0。后续再遇到相同的元素时,便不会向result种进行尾插,达到了去重的目的。对于代码如下:
 

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {

     int hash[1001] = {0};

     for(int i = 0; i < nums1.size(); i++)
     {
        hash[nums1[i]] = 1;
     }

     vector<int> result;
    
     for(int j = 0; j < nums2.size(); j++)
     {
        if(hash[nums2[j]] == 1)
        {
            result.push_back(nums2[j]);
          
            hash[nums2[j]] = 0;
        }
     }

     return result;

    }
};

运行结果如下:

Leetcode.202 快乐数:

202. 快乐数 - 力扣(LeetCode)

       对于本题,难点在于理解题干中的信息。对于快乐数的定义,题目中已经给了19的样例,因此不再进行过多解释。但是在题干中,提到了在求快乐数的过程中,将这个数替换为每个位置上的数字的平方和的过程是无限循环的,例如文章给定一个数2,则求解2是否为快乐数的过程可以由下图表示:

而对于题目中给的样例19,求解其是否是快乐数的过程如下:

不难发现,当一个数经过若干次计算,得到的结果为1时,则后续的结果便是无限循环1,因此,也可以把1这个过程看作上面菲快乐数的成环过程,即:

       不过上面给出的例子只是两个个例,并不具备普遍性,由此会引起一个问题:对于一个数I,I可以是任意一个正整数,均存在上面的环状循环过程吗?对于这一过程,下面将使用鸽巢原理进行证明:

      对于鸽巢原理,其大体内容为:存在n个巢,n+1个鸽子,则必定存在一个巢,里面的鸽子数量>1,假设取一个数为9999999999,即10个数位上都是9。如果对这个最大的数值进行一次上面的操作,则不难得出,这个数是一定小于810的,因此,对于这个数据在求解快乐数时产生的数据的范围一定是[1,810],假设,每进行一次上方的运算,都会得到一个属于上面区间中的不同的数值,那么,在进行811次操作后,一定会得到一个和之前某次运算得到的值相同的值。因此,如果运算次数够多,对于任何一个数,均存在一个无限循环。

     在证明了一定会出现环状循环后,便可以进行解题:

       首先创建一个函数用于进行一次上面计算欢乐数的过程,这里将这个函数命名为multvalue,并且创建一个变量用于接收函数的返回值,这里将这个变量命名为value。通过set创建一个哈希表,这里命名为hash

      每进行一次计算,便进行一次判断,如果value==1,则说明是快乐数,返回true,如果不是,则首先查找这个数是否在hash中出现过,如果出现过,则说明进入了上图中非快乐数的死循环,返回false,反之则将这个数存放在hash中。具体代码如下:

class Solution {
public:
    
    int multvalue(int n)
    {
        int sum = 0;
        int t = 0;
        while(n)
        {
            t = n%10;//取n的最小位上的数
            sum += t*t;//
            n = n/10;//去掉最小位

        }
        return sum;
    }
    bool isHappy(int n) {
        unordered_set<int> hash;

        int value = n;
        while(1)
        {
            value = multvalue(value);

            if(value == 1)
            {
                return true;
            }

            if( hash.find(value) != hash.end())
            {
                return false;
            }
            else
            {
                hash.insert(value);
            }
        }

    }
};

运行结果如下:

    

Leetcode.1 两数之和—梦开始的地方:

1. 两数之和 - 力扣(LeetCode)

        对于本题,依然可以使用哈希的思想进行解题,具体如下:
        首先利用map创建一个哈希表,具体结构为:第一个位置存放数值,第二个位置存放该数值所对应的下标。同时创建一个vector<int>类型的对象v用于存储返回值首先对给定的nums进行遍历,每当遍历一个数值时,在哈希表中对target-nums[i]这个数值进行查询。此时会出现两种情况:

        如果存在这个数,则表示找到了这个数,同时将这个数所对应的数值以及下标插入到v中,返回v

      如果不存在target-nums[i],则将nums[i],i这两个数值插入到哈希表中。循环上述过程。

下面将通过一组例子,来对上述过程进行图像化的说明:

     例如,给定上图所示的数字,且需要查找的目标和为target,在进行循环时,首先对数组的第一个元素2进行判断,即:去哈希表中,找是否存在target-nums[0] = 7这个数,此时不存在,则向哈希表中插入nums[0],0,即:

       对元素5进行判断,查找哈希表中是否存在target-nums[1] = 4这个数值,由于不存在,因此,向哈希表中插入nums[1],1,即:

       对元素7进行判断,查找哈希表中是否存在target-nums[2]=2这个数值,此时存在,则向v中插入这两个数的下标,即0,2。返回v。对应代码如下:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
         std::unordered_map <int,int> hash;
         vector<int> v;

         for(size_t i = 0; i < nums.size(); i++)
         {
            auto iter = hash.find(target-nums[i]);
            if(iter != hash.end())
            {
                v.push_back(i);
                v.push_back(iter->second);
                return v;
            }

            hash.insert(pair<int, int>(nums[i], i));
         }
         return v;
        
    }
};

运行结果如下:

    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

起床写代码啦!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值